larswm-7.5.3/0000755000000000000000000000000010075553553013001 5ustar rootroot00000000000000larswm-7.5.3/bar.c0000644000000000000000000001630410065667625013722 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" #define MSGSIZE 100 static char cmd_output[MSGSIZE + 1]; static char *cmd_output_ptr = 0; int bar_hidden = 0; #define MENU_BASE -10 #define MENU_ENTRIES 6 static char *menu[] = { "Menu [1/6] Toggle clickthru (Desktop)", "Menu [2/6] Toggle tile_resize (Desktop)", "Menu [3/6] Toggle skip_focus (Desktop)", "Menu [4/6] Toggle floatclass (Window)", "Menu [5/6] Toggle toolclass (Window)", "Menu [6/6] Toggle stickyclass (Window)", }; /* Make sure all menu entries really are this length! */ #define MLEN 41 void do_menu (ScreenInfo * s) { if ((bar_hidden >= 0) && (numhidden > 0) && (bar_hidden < numhidden)) { bar_hidden = numhidden; update_tbar (); } else switch (-bar_hidden + MENU_BASE) { case 0: toggle_clickthru (s); break; case 1: toggle_tile_resize (s); break; case 2: toggle_skip_focus (s); break; case 3: toggle_isfloat (current); break; case 4: toggle_istool (current); break; case 5: toggle_issticky (current); break; } } void prev_menu (void) { if ((bar_hidden >= 0) && (numhidden > 0) && (bar_hidden < numhidden)) { bar_hidden = numhidden; } else { bar_hidden++; if ((bar_hidden > MENU_BASE) && (bar_hidden < numhidden)) bar_hidden = numhidden; else if (bar_hidden > MENU_BASE) bar_hidden = MENU_BASE - (MENU_ENTRIES - 1); } update_tbar (); } void next_menu (void) { if ((bar_hidden >= 0) && (numhidden > 0) && (bar_hidden < numhidden)) { bar_hidden = numhidden; } else { bar_hidden--; if (bar_hidden > MENU_BASE) bar_hidden = MENU_BASE; else if (bar_hidden < (MENU_BASE - (MENU_ENTRIES - 1))) bar_hidden = numhidden; } update_tbar (); } void show_hidden (void) { if (bar_hidden < 0) { bar_hidden = numhidden; update_tbar (); } else if ((bar_hidden >= 0) && (numhidden > 0) && (bar_hidden < numhidden)) { Client *c = hiddenc[bar_hidden]; unhide (bar_hidden, 1); if (!c->isnotile) tile_all (c->screen); } else if (current) { hide (current); } } void prev_hidden (void) { bar_hidden--; if (bar_hidden < 0) bar_hidden = numhidden; update_tbar (); } void next_hidden (void) { bar_hidden++; if (bar_hidden < 0) bar_hidden = numhidden; else if (bar_hidden > numhidden) bar_hidden = 0; update_tbar (); } void update_cmd_output (void) { XTextProperty pr; cmd_output_ptr = 0; if (XGetTextProperty (dpy, DefaultRootWindow (dpy), &pr, bartext_larswm)) { if (pr.nitems > 0) { strncpy (cmd_output, (char *) pr.value, MSGSIZE); cmd_output[MSGSIZE] = '\0'; cmd_output_ptr = cmd_output; } XFree (pr.value); } update_tbar (); XSync (dpy, False); } void draw_tbar (ScreenInfo * s) { int tlen, max_tlen; char sbar[256], tmp[256]; if (!s) return; XClearWindow (dpy, s->barwin); #ifdef THREE_D XDrawLine (dpy, s->barwin, s->botwhitegc, 0, BAR_HEIGHT - 1, BAR_WIDTH (s) - 1, BAR_HEIGHT - 1); XDrawLine (dpy, s->barwin, s->botwhitegc, BAR_WIDTH (s) - 1, BAR_HEIGHT - 1, BAR_WIDTH (s) - 1, 0); XDrawLine (dpy, s->barwin, s->topwhitegc, 0, 0, BAR_WIDTH (s) - 1, 0); XDrawLine (dpy, s->barwin, s->topwhitegc, 0, 0, 0, BAR_HEIGHT - 1); #endif sbar[0] = '\0'; if (current && (current->screen == s) && !((bar_hidden >= 0) && (bar_hidden < numhidden))) { strcpy (sbar, "("); if (current->class) strcat (sbar, current->class); strcat (sbar, "~"); if (current->instance) strcat (sbar, current->instance); strcat (sbar, ") ["); tmp[0] = current->isnotile ? 'n' : '-'; tmp[1] = current->isfloat ? 'f' : '-'; tmp[2] = current->istool ? 't' : '-'; tmp[3] = current->issticky ? 's' : '-'; tmp[4] = current->iszoom ? 'z' : '-'; tmp[5] = ']'; tmp[6] = ' '; tmp[7] = ' '; tmp[8] = '\0'; strcat (sbar, tmp); } if (! ((bar_hidden <= MENU_BASE) || ((bar_hidden >= 0) && (bar_hidden < numhidden)))) { strcat (sbar, prefs.dtname[s->num][s->desktop]); strcat (sbar, " "); } tmp[0] = '['; tmp[1] = s->notile_raised[s->desktop] ? 'U' : 'T'; tmp[2] = s->clickthru[s->desktop] ? 'C' : '-'; tmp[3] = s->tile_resize[s->desktop] ? 'R' : '-'; tmp[4] = s->skip_focus[s->desktop] ? 'S' : '-'; tmp[5] = s->bigmr[s->desktop] ? 'B' : '-'; tmp[6] = numhidden ? 'H' : '-'; tmp[7] = ']'; tmp[8] = '\0'; strcat (sbar, tmp); if (! ((bar_hidden <= MENU_BASE) || ((bar_hidden >= 0) && (bar_hidden < numhidden)))) { if (cmd_output_ptr) { strcat (sbar, " "); strcat (sbar, cmd_output); } } tlen = strlen (sbar); if (tlen > 0) { int plen = XTextWidth (font, sbar, tlen); XDrawString (dpy, s->barwin, s->gc, BAR_WIDTH (s) - plen - BAR_HEIGHT, BAR_TEXT_Y, sbar, tlen); /* space left on left */ max_tlen = BAR_WIDTH (s) - plen - (3 * BAR_HEIGHT); if (max_tlen < 1) max_tlen = 1; } /* print current window's label */ if (bar_hidden <= MENU_BASE) { XDrawString (dpy, s->barwin, s->gc, BAR_HEIGHT, BAR_TEXT_Y, menu[-bar_hidden + MENU_BASE], MLEN); } else if ((bar_hidden >= 0) && (bar_hidden < numhidden)) { Client *c = hiddenc[bar_hidden]; unsigned short int changed = 0; if (c->screen == s) sprintf (tmp, "Hidden [%d/%d] %s", bar_hidden + 1, numhidden, c->iconname ? c->iconname : c->label); else sprintf (tmp, "Other Screen [%d/%d] %s", bar_hidden + 1, numhidden, c->iconname ? c->iconname : c->label); tlen = strlen (tmp); while (tlen > 0 && XTextWidth (font, tmp, tlen) > max_tlen) { tlen--; changed = 1; } if (changed && tlen > 10) { tmp[tlen - 3] = '\0'; strcat (tmp, "..."); } if (tlen > 0) { XDrawString (dpy, s->barwin, s->gc, BAR_HEIGHT, BAR_TEXT_Y, tmp, tlen); } } else if (current && current->label && (current->screen == s)) { unsigned short int changed = 0; strcpy (tmp, current->label); tlen = strlen (tmp); while (tlen > 0 && XTextWidth (font, tmp, tlen) > max_tlen) { tlen--; changed = 1; } if (changed && tlen > 10) { tmp[tlen - 3] = '\0'; strcat (tmp, "..."); } if (tlen > 0) { XDrawString (dpy, s->barwin, s->gc, BAR_HEIGHT, BAR_TEXT_Y, tmp, tlen); } } } void update_tbar (void) { int i; for (i = 0; i < num_screens; i++) draw_tbar (&screens[i]); } void raise_tbar (ScreenInfo * s) { Client *c; if (!s) return; for (c = clients; c; c = c->next) if ((c->isfloat || c->isaside) && normal (c) && (c->screen == s) && (c->issticky || (c->desktop == c->screen->desktop))) XMapRaised (dpy, c->parent); XMapRaised (dpy, s->barwin); } ScreenInfo * getbarscreen (Window w) { int i; for (i = 0; i < num_screens; i++) { if (screens[i].barwin == w) return &screens[i]; } return 0; } larswm-7.5.3/buttons.c0000644000000000000000000002276710065667625014666 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" Client *hiddenc[MAXHIDDEN]; int numhidden = 0; void button (XButtonEvent * e) { Client *c; ScreenInfo *s; Window dw; s = getscreen (e->root); if (s == 0) return; if (e->window == s->barwin) { if (current && current->screen == s) cmapnofocus (s); switch (e->button) { case Button1: if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) == (ShiftMask | ControlMask | Mod1Mask)) { if (current && current->isnotile && (current->screen == s)) resize_opaque (current); } else if ((e->state & (ControlMask | ShiftMask)) == (ControlMask | ShiftMask)) grow (current, DIM_VERT | DIM_HORIZ, -1); else if ((e->state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) move_aside (s, (Client *) 0); else if ((e->state & (ShiftMask | Mod1Mask)) == (ShiftMask | Mod1Mask)) { if (current && current->isnotile && (current->screen == s)) move_opaque (current); } else if ((e->state & ControlMask) == ControlMask) prev_menu (); else if ((e->state & Mod1Mask) == Mod1Mask) prev_hidden (); else prev_desktop (s); break; case Button2: if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) == (ShiftMask | ControlMask | Mod1Mask)) { if (current && (current->screen == s)) XLowerWindow (dpy, current->parent); } else if ((e->state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) move_aside (s, current); else if ((e->state & (ControlMask | ShiftMask)) == (ControlMask | ShiftMask)) move_select (current, 0); else if ((e->state & ControlMask) == ControlMask) do_menu (s); else if ((e->state & Mod1Mask) == Mod1Mask) show_hidden (); else toggle_notile (s); break; case Button3: if ((e->state & (ShiftMask | ControlMask | Mod1Mask)) == (ShiftMask | ControlMask | Mod1Mask)) zoom (current, (DIM_VERT | DIM_HORIZ)); else if ((e->state & (ControlMask | ShiftMask)) == (ControlMask | ShiftMask)) grow (current, DIM_VERT | DIM_HORIZ, 1); else if ((e->state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) move_aside_clear (s, current); else if ((e->state & ControlMask) == ControlMask) next_menu (); else if ((e->state & Mod1Mask) == Mod1Mask) next_hidden (); else next_desktop (s); break; case Button4: if ((e->state & (ControlMask | ShiftMask | Mod1Mask)) == (ControlMask | ShiftMask | Mod1Mask)) move_up (current); else if ((e->state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) move_aside (s, (Client *) 0); else if ((e->state & (Mod1Mask | ShiftMask)) == (Mod1Mask | ShiftMask)) move_left (current); else if ((e->state & (ControlMask | ShiftMask)) == (ControlMask | ShiftMask)) grow (current, DIM_VERT | DIM_HORIZ, -1); else if ((e->state & ControlMask) == ControlMask) prev_menu (); else if ((e->state & Mod1Mask) == Mod1Mask) prev_hidden (); else if ((e->state & ShiftMask) == ShiftMask) prev_window (s); else prev_desktop (s); break; case Button5: if ((e->state & (ControlMask | ShiftMask | Mod1Mask)) == (ControlMask | ShiftMask | Mod1Mask)) move_down (current); else if ((e->state & (ControlMask | Mod1Mask)) == (ControlMask | Mod1Mask)) move_aside_clear (s, current); else if ((e->state & (Mod1Mask | ShiftMask)) == (Mod1Mask | ShiftMask)) move_right (current); else if ((e->state & (ControlMask | ShiftMask)) == (ControlMask | ShiftMask)) grow (current, DIM_VERT | DIM_HORIZ, 1); else if ((e->state & ControlMask) == ControlMask) next_menu (); else if ((e->state & Mod1Mask) == Mod1Mask) next_hidden (); else if ((e->state & ShiftMask) == ShiftMask) next_window (s); else next_desktop (s); break; } if (current && current->screen == s) cmapfocus (current); return; } /* don't let clicks that "bleed" through clients look like they were on the root window. */ if (!(c = getclient (e->window, 0)) && (e->subwindow != None) && (c = getclient (e->subwindow, 0))) XTranslateCoordinates (dpy, e->root, e->subwindow, e->x, e->y, &e->x, &e->y, &dw); if (current && current->screen == s) cmapnofocus (s); switch (e->button) { case Button1: if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER)) && (e->y >= BORDER) && (e->y < (c->dy + BORDER))) { int wasleft = c->isleft; int wasaside = c->isaside; int ctrl = (e->state & ControlMask) == ControlMask; int skip = s->skip_focus[s->desktop]; if (ctrl && !c->isnotile) skip = !skip; if (c->isnotile != s->notile_raised[s->desktop]) { if (c->isnotile || s->skip_focus[s->desktop]) skip = 1; if (!ctrl) toggle_notile (s); } if ((!skip && !c->isnotile) || (!ctrl && c->isnotile)) { raise_tbar (c->screen); XMapRaised (dpy, c->parent); top (c); } active (c); if (wasaside) { move_aside (c->screen, c); if (ctrl) move_aside_other (c->screen); } else if (!skip && !c->isnotile) tile_all (s); if ((skip || wasleft || c->isnotile) && !ctrl && !wasaside && s->clickthru[s->desktop] && (c->istool || c->isfloat || (c->isnotile == s->notile_raised[s->desktop]))) XAllowEvents (dpy, ReplayPointer, e->time); } else if (prefs.btnapplication[0]) spawn (s, prefs.btnapplication[0]); break; case Button2: if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER)) && (e->y >= BORDER) && (e->y < (c->dy + BORDER))) { if (s->clickthru[s->desktop] && !c->isaside && (c->istool || c->isfloat || (c->isnotile == s->notile_raised[s->desktop]))) { active (c); XAllowEvents (dpy, ReplayPointer, e->time); } } else if (prefs.btnapplication[1]) spawn (s, prefs.btnapplication[1]); break; case Button3: if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER)) && (e->y >= BORDER) && (e->y < (c->dy + BORDER))) { if (s->clickthru[s->desktop] && !c->isaside && (c->istool || c->isfloat || (c->isnotile == s->notile_raised[s->desktop]))) { active (c); XAllowEvents (dpy, ReplayPointer, e->time); } } else if (prefs.btnapplication[2]) spawn (s, prefs.btnapplication[2]); break; case Button4: if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER)) && (e->y >= BORDER) && (e->y < (c->dy + BORDER))) { if (s->clickthru[s->desktop] && !c->isaside && (c->istool || c->isfloat || (c->isnotile == s->notile_raised[s->desktop]))) { active (c); XAllowEvents (dpy, ReplayPointer, e->time); } } break; case Button5: if (c && (e->x >= BORDER) && (e->x < (c->dx + BORDER)) && (e->y >= BORDER) && (e->y < (c->dy + BORDER))) { if (s->clickthru[s->desktop] && !c->isaside && (c->istool || c->isfloat || (c->isnotile == s->notile_raised[s->desktop]))) { active (c); XAllowEvents (dpy, ReplayPointer, e->time); } } break; } if (current && current->screen == s) cmapfocus (current); } void spawn (ScreenInfo * s, char *p) { /* * ugly dance to avoid leaving zombies. Could use SIGCHLD, * but it's not very portable. */ if (fork () == 0) { if (fork () == 0) { close (ConnectionNumber (dpy)); if (s->display[0] != '\0') { putenv (s->display); } if (p) { execl (shell, shell, "-c", p, 0); fprintf (stderr, "larswm: execl %s", shell); perror (" failed"); } else { execlp ("xterm", "xterm", 0); fatal ("execlp xterm"); } } exit (0); } wait ((int *) 0); } void wmdelete (Client * c, int shift) { if (c == 0) return; if ((c->proto & Pdelete) && !shift) sendcmessage (c->window, wm_protocols, wm_delete, 0); else XKillClient (dpy, c->window); /* let event clean up */ } void hide (Client * c) { if (c == 0 || numhidden == MAXHIDDEN) return; if (hidden (c)) return; XUnmapWindow (dpy, c->parent); XUnmapWindow (dpy, c->window); wmsetstate (c, IconicState); if (c == current) { revert_window (c->screen); } hiddenc[numhidden] = c; numhidden++; c->hidden = 1; bar_hidden = numhidden; update_tbar (); } void unhide (int n, int map) { Client *c; int i; if (n >= numhidden) return; c = hiddenc[n]; if (!hidden (c)) return; if (map) { c->desktop = c->screen->desktop; raise_tbar (c->screen); XMapWindow (dpy, c->window); XMapRaised (dpy, c->parent); wmsetstate (c, NormalState); top (c); active (c); } numhidden--; for (i = n; i < numhidden; i++) hiddenc[i] = hiddenc[i + 1]; c->hidden = 0; bar_hidden = numhidden; if (map && (c->isnotile != c->screen->notile_raised[c->screen->desktop])) toggle_notile (c->screen); update_tbar (); } void unhidec (Client * c, int map) { int i; if (!c->hidden) return; for (i = 0; i < numhidden; i++) if (c == hiddenc[i]) { unhide (i, map); return; } } void renamec (Client * c, char *name) { if (name == 0) name = "???"; c->label = name; } larswm-7.5.3/ChangeLog0000644000000000000000000025265010075553507014564 0ustar rootroot000000000000001.0 - Jun 3, 2000: 1. Initial version. Added tiling to 9wm. 1.1 - Jun 5, 2000: 1. Added support for max size hints. 2. Also, Things with width_inc and height_inc should look better now. 1.2 - Jun 5, 2000: 1. Incorporated ideas/code from Benjamin Drieu's w9wm project, so now it has virtual desktops, currently hardcoded at four. 1.3 - Jun 6, 2000: 1. Fixed a bug with PMaxSize windows that set hints after the window has been mapped. 2. Fixed some other small bugs. 1.4 - Jun 6, 2000: 1. Added support for Prev. Desktop. 2. When toggling Auto ReTile, it toggles for the current desktop only! Now you can have some desktops auto tile, and some behave more traditional. 3. Added support for Button4 and Button5. Button4 switches to previous desktop, Button5 to next. If you have a wheel mouse, put: ZAxisMapping 4 5 in your XF86Config to use wheel up and down to switch desktops. 4. Added the -rv option. Reverses black/white in all window manager menus/windows. 1.4.1 - Jun 7, 2000: 1. Fixed the way transient windows are raised, now nested transients work properly. 2. renamed setstate() to wmsetstate() to avoid clashing with the function of the same name in stdlib.h. 3. Fixed a bug in how transient windows are hidden and restored when moving between desktops. 1.5 - Jun 8, 2000: 1. Added support for 'tools', applications you always want visible on the screen and not included in the retiling process. See -toolspace and -toolclass command line options. 2. Fixed some minor cosmetic bugs. Using all screen space optimally. 2.0 - Jun 9, 2000: 1. Added support for multi-screen displays. You can change desktop, default number of windows in left track, auto tiling on/off individually for each screen. You can also pick which screen you want toolspace reserved on. 2.1 - Jun 15, 2000: 1. Added support for focusing a window without retiling everything, even if auto tiling is on for that screen/desktop. Just Ctrl-LeftClick on an inactive window. 2. Added an option to always act as if window selects were done with Control held down. 3. Added an option to balance tracks. This makes sure that both tracks have the same width and number of windows in them. Works nice with SkipFocus for an Oberon effect. 2.2 - Jun 27, 2000: 1. Added the -nouserhints option. Now by default, if the user specifies the position of a window, it will not be included in the tiling process. This can be used instead of -toolclass as a way of not having to specify every kind of window you don't want tiled, or if you want some but not all windows of a class tiled. 2. If the argument to -toolspace is a negative number, space is reserved at the top of the screen instead of the bottom. 3. Added the -widetools option. This makes the reserved toolspace stretch across the screen, not just across the right track. 3.0 - Jun 28, 2000: 1. Big cleanup. Removed -toolspace, -toolclass -toolscreen and -widetools options. Now tools are looked for at each retiling event, and anything that has had its position specified by the user is considered a tool. Where to set aside toolspace (top or bottom, right track only or full width) is calculated. When a tool pops up, it might end up on top of a tiled window, it will be properly tiled when the next retiling event occurs. 3.1 - Jun 30, 2000: 1. Rearranged all menus. :) Here's how the menus work, they can be popped up anywhere on the root window, or over an inactive window. Mouse Button Function/Menu ------------------------------------------------ Right Make clicked window active. Control+Right Active, without retiling. Middle Next Desktop. Shift+Middle List all Desktops. Control+Middle Previous Desktop. Left Main menu, same as 9wm. Shift+Left Hidden Windows. Control+Left larswm functions. Shift+Control Left or Right shows version info. ------------------------------------------------ 2. Cleaned up the usage of pointers to active window on each desktop. This should eliminate one obscure crashing bug. 3. When the current window goes away on a screen, it will not revert to a window on a different screen. If any focus change happens, it will be to the screen that was just manipulated. 3.1.1 - Jul 3, 2000: 1. Minor tweak to how it remembers which window has focus on a particular destkop. Now tools will not be remembered. Makes for a little more consistent behaviour. 3.2 - Jul 3, 2000: 1. Another bigger cleanup. The Toggle Balance Tracks option has been replaced with a generic layout menu. Control+Shift+Right mouse button brings it up. Right now the options are: Normal, 2/3 focused, 1/3 rest. Square, focused window is as wide as the screen is tall. Balanced, like the old balanced tracks, same width and number of windows in each track. The separate Left Track Num Windows option has been removed. 2. Changed the default fonts. Now it will try "variable" and if that fails, "fixed". 3. You can toggle whether larswm sees a client as a tool or not by Shift+Left clicking on it. 4.0b1 - Jul 4, 2000: 1. Added keyboard support. Please see summary below. This is released as a beta version, as I'm still not sure if I got all those XKeyGrabs right... 4.0b2 - Jul 4, 2000: 1. Uhh, I was sleepy when I put b1 out. Some pointers were omitted from some calls to initkeys, somehow this did not coredump on linux/sparc64... 4.0b3 - Jul 4, 2000: 1. Added keyboard shortcuts for moving between screens. Control-PageUp and Control-PageDown goes back and forth between your screens (physical monitors). 4.0b4 - Jul 4, 2000: 1. All Control+something shortcuts have been changed to Shift+Control+something, to lessen the risk of overlapping with applications. 4.0b5 - Jul 4, 2000: 1. Added -bg and -fg options to set larswm menu and border colors. At this time there are no plans for more elaborate "theming" capabilities. :) Removed -rv, as it is obsolete now. 2. Now Shift+Control is used as the modifier for all larswm functions. Consistency is a virtue. Alt-Tab is still provided since that seems to be a de facto standard. 3. Cleaned up the names of the command line options. See below for the complete list. 4.0b6 - Jul 4, 2000: 1. Fixed the bug where it wouldn't retile around tools as they pop up. 2. Events on a different screen from the one containing the focused window will retile that screen. 3. A window will not automatically get focus on a screen that does not have the mouse pointer in it unless that same screen also contains the currently focused window. One more step towards always knowing where your keystrokes are going... :) 4. Default terminal program is xterm, even if 9term is installed. Use the -term option to set your preferred terminal. 4.0 - Jul 5, 2000: 1. Updated docs. Everything else seems stable. Changed version number to 4.0. 4.1b1 - Jul 7, 2000: 1. Added -display option. 2. Cleaned up code. No more K&R C function definitions. 3. Added restart/exit menu. Shift+Control+Right mouse. 4. Added .larswmrc support! You can use the -defaults option to have it print out a properly formatted config file that you can edit to your taste. cd $HOME larswm -defaults > .larswmrc Documentation on this will be updated when features have been finalized. 4.1b2 - Jul 7, 2000: 1. Added the larswm.badclass keyword to rc format. Use this to force a window of the specified class to be tiled even if it insists that the user specified the position. This will help with applications like kvirc and LyX. 4.1b3 - Jul 7, 2000: 1. Added the larswm.desktops keyword to rc format. This will let you set how many virtual desktops you want per physical screen. You can chose between 1 and 32, default is 4. 4.1b4 - Jul 7, 2000: 1. Added the larswm.application_# keyword to rc format. This lets you add commands to be executed from the application menu, Shift+Control+Left mouse. Enter them like this, the number on the end decides which order they will be in, the lines can appear in any order in the rc file and there can be gaps in the number sequence. larswm.application_0: netscape larswm.application_1: xcalc 2. Fixed a design flaw in how badclass is loaded from rc. Same numbering rules applies as for application resource lines. You need to enter them like this: larswm.badclass_0: BadApp1 larswm.badclass_1: BadApp2 3. Changed max number of applications, badclasses and virtual desktops to 64. At least for desktops, think of 64 as the theoretical max. I can't imagine actually having 64 desktops and trying to find your windows. :) 4.1b5 - Jul 7, 2000: 1. Fixed a bunch of typos in prefs.c. Now keyboard mapping will really work for all functions. This should be the last beta in the 4.1 series. *cross fingers*. 2. If you typo the key symbol in the rc file, it will reset all defaults, so if you seem to not get your preferences, check the key entries. 4.2 - Jul 8, 2000: 1. Added a simple man page. It's mostly there for command line options, and to point to where the real documentation can be found. 2. Changed version from beta 4.1 to stable 4.2. 4.3b1 - Jul 9, 2000: 1. Fixed a bug with -display, where it wouldn't open new windows on the correct display. 2. Changed number of desktops to 32 to save memory and startup time. Now supports max 8 physical screens. Both of these numbers can be changed in dat.h if needed. 3. Added configurability per screen/desktop for the following resources: larswm.auto_retile larswm.skip_focus larswm.layout The format for these resources should now be larswm.resource[x][y]: value where x is screen number and y is desktop number. 0 means first screen/desktop. if you omit one number, it means all of the screens/desktops. Example: larswm.auto_retile[][3]: false means do not auto retile on virtual desktop 3 on all physical screens. 4. Changed the format of application, badclass and goto_desktop keyboard shortcut resources to be more consistent with the other indexed formats. 4.3b2 - Jul 9, 2000: 1. Changed the order in which indexed prefs are looked for, making it possible to specify for instance: larswm.auto_retile[][]: false larswm.auto_retile[0][]: true which would only auto retile on the first physical screen. 4.3b3 - Jul 9, 2000: 1. Added the resource larswm.left_track_width[][] which sets how wide the left track should be when the default layout is active in the specified screen/desktop. The unit is percent of screen width, the valid choices are 5-95 and the default is 66. 2. Added resource larswm.left_track_numwindows[][] which sets the number of windows to tile in the left track when using the Default layout on the specified screen/desktop. At least 1, and default is 1. 3. Indexed resources can be specified in these ways: res = v - All screens and all desktops. res[][] = v - Same as above. res[d] = v - All screens and desktop #d. res[][d] = v - Same as above. res[s][] = v - Screen #s and all desktops. res[s][d] = v - Screen #s and desktop #d. More specific indexing overrides more generic. This is true for all resources that has [][] after the name in the -defaults printout. 4.4 - Jul 10, 2000: 1. Split change log into its own file. 2. Upped version to 4.4 and announced it as stable. 4.4.1 - Jul 10, 2000: 1. Allow down to zero width borders. 2. Add larswm.toolclass[#] option. Up to 64 classes of windows that will not be tiled even if USPosition is not set. 3. Cleaned up layout menu. 4.4.2 - Jul 11, 2000: 1. Now correctly handles windows that set the input member of the WM_HINTS property to False. These windows will not get focus, either automatically or by clicking on them. 4.4.3 - Jul 12, 2000: 1. Simplifed the way window borders are drawn. Now they consist of only one color at a time, and borders can really be 0 width. 2. Cleaned out some old 9term stuff, since hold mode isn't shown with the new borders anyway. 3. larswm.inset was removed because of 1 and 2. 4. Added larswm.tile_pad, which will set how many pixels there should be between the windows when they are auto tiled. Default is 2. 5. Changed the default for larswm.blitcursors and larswm.grey to False. 4.4.4 - Jul 12, 2000: 1. Augh! A bug crept in while I wasn't watching. Crashing when xev and possibly other apps open is now fixed. 2. System specific include files have been replaced with Xos.h as much as possible. 4.9b1 - Jul 13, 2000: 1. Major tweaking! Now can show window title bars at the top of the windows. No fancy decorations or buttons, just a label to help keep track of all those xterms. :) Default is off, turn on with: larswm.titles: True in the .larswmrc file. When clicking a mouse button in the title bar, it means does the same thing as if you clicked on an inactive window. In other words, no special things like dragging a window by the title bar. I'm tempted to say that if you really need that, this might not be the best window manager for you. :) 2. As a side effect of adding title bars, I've had to really dig into the code (grab.c still scares me) and make small modifications here and there. Hopefully I didn't break it too bad, but I think it might be a good idea if this stays beta for at least a week or so. :) 4.9b2 - Jul 13, 2000: 1. Moved title bar to bottom edge of windows. This might seem weird, but I kinda like it. Remember, title bars are optional. They will not appear unless you specifically add this line to your .larswmrc: larswm.titles: True 4.9b3 - Jul 13, 2000: 1. Added the following configurable keyboard shortcuts. Shift+Control+comma: shrink left track. Shift+Control+period: expand left track. Shift+Control+Home: maximize left track. Shift+Control+End: restore left track. Use larswm -defaults to see resource names. 4.9b4 - Jul 15, 2000: 1. Added the larswm.tile_resize[][] option, with a default of True. If this is false, windows are not actually resized when put in the right track, but instead just stacked on top of eachother, with a portion at the top of each window visible. Use this on screens where you run netscape for instance, to speed up refocusing (netscape won't have to recalculate layout since it's not resized). 2. Added a small status display to the title bar of the focused window. The display looks like this: +0+ -1- [2] -3- (2) {14} This means: Desktop 0 has open windows. Desktop 1 does not have open windows. Desktop 2 is currently visible. Desktop 3 does not have open windows. There are 2 hidden windows on this screen. There are 14 windows on other screens. If there are no windows on other screens, or no hidden windows, the () and {} will not be displayed. I could have made icons for this, but... looking fancy is not really the goal here. :) 3. Small improvement in how it handles tool windows, they will now always stay on top of other windows, except the focused window. Useful when using the tile_resize: False option. 4. Transient windows will open on any desktop, but as soon as you switch desktop, it will only be visible on the same desktop as its parent window. This way you shouldn't miss any important messages, while at the same time not have to find stray dialog boxes hanging around the wrong desktop. 4.9b5 - Jul 15, 2000: 1. Fixed a small bug where toolspace would not be calculated when in tile_resize: False mode. 4.9b6 - Jul 15, 2000: 1. Fixed a subtle bug with override_redirect windows who grab keyboard focus (for example, the netscape menubar) and end up underneath the main window. This was fixed by changing how the retiling event is generated. No retiling will be done as a result of any focus event, but as a result of the mouse click instead. 2. Changed the 'toggle toolstatus' from Shift+Left mouse to making it a menu choice in the tiling menu. If you select 'Toggle Tool Window', the cursor changes into the crosshairs. Just right click on the window you want to toggle between being considered a tool window or not. 3. Removed some redundant initkeys() calls. 4. Fixed a bug in how number of hidden windows were counted. Now also counts hidden tools. 4.9b7 - Jul 16, 2000: 1. Do not waste screen space for the nonexistent titlebar when tiling shaped windows. 2. Tool windows will not have title bars. 3. Changed a couple of default limits. Now supports 4 physical screens of 16 virtual desktops each. Edit dat.h if you need more. 4.9b8 - Jul 16, 2000: 1. Cleaned up XSetInputFocus calls. timestamp() was removed. 2. Cleaned up a couple of menus. No more menu titles. Will not popup hidden windows menu unless there are hidden windows. Same for Applications. 3. Fixed a rare bug in title bar drawing that would show up sometimes when the window would be mapped before the WM_NAME was set. 4. Adjusted some defaults. 32 apps, 32 hidden windows. 32 badclass and toolclass entries. Edit dat.h if you need more. 4.9b9 - Jul 17, 2000: 1. Swapped Maximize and Restore left track keys. Default is now: Shift+Control+End = maximize and Shift+Control+Home = restore default. I find this more intuitive. 2. Removed larswm.grey and larswm.blitcursors options. Use xsetroot or something like that to set screen background. Uses only blit lookalike cursors. 3. Removed some redundant code dealing with focus. Added simplified and more predictable way to revert to previously active window when auto tiling is off. 4. Now properly raises windows when using the keyboard shortcuts to move to next and previous windows if not in auto retile mode. 5. When on a desktop without auto retiling, clicking a window will focus and raise. Control+clicking will focus without raising it. This behaviour is reversed if the desktop also has skip_focus set. 5.0 - Jul 17, 2000: 1. Version changed to stable 5.0. 5.0.1 - Jul 18, 2000: 1. Using only X11 built-in mouse pointers. The cursor.c file was removed from the distribution. 2. Fixed a small bug where if you had auto retiling off an app that starts iconified still wanted to be placed on the desktop. 3. Removed the 'exit' and 'restart' command line options. Exit using the exit/restart menu which is on Shift+Control+Right mouse button. 4. Simplified how it determines what is the next and previous window, and how it reverts to the previous window in the stacking order when the active window closes. No more having to hit Shift+Control+Up or Down twice after jumping to a different screen sometimes. 5. Code cleanup. Removed little snippets here and there that wasn't being used. 5.0.2 - Jul 18, 2000: 1. By popular demand, command line exit and restart are back. :) 2. Some more tweaks to focus handling when warping between screens. Still not perfect. 3. Added the larswm.run_dialog option. This can be used to specify an application to use as program launcher. 4. Added the larswm.run_dialog_key and run_dialog_mod options to set the keyboard shortcut for the run dialog. 5. Fixed a bug with Goto desktop #X shortcuts. 5.1b1 - Jul 19, 2000: 1. Added the larswm.notileclass[#] option. You can add up to 32 window classes that will not be tiled but instead kept in their own group on each desktop. 2. Added the larswm.raise_notile_key and mod options to set the keyboard shortcut you want to use to raise all untiled windows on the current desktop. If there is a current window, and it is an untiled window, then this function will lower all untiled windows. The default key is Shift+Control+BackSpace. 3. When using previous and next window shortcuts, only move to another window of the same type as far as notileclass goes. 4. The effect is like a separate desktop within every desktop that is for untiled windows only. Each screen/desktop remembers if tiled or untiled windows were last used. 5.1b2 - Jul 19, 2000: 1. Added the larswm.application_key[number] and larswm.application_mod[number] options. Use this to create keyboard shortcuts to the corresponding larswm.application[number] entries. Make sure you use the same number for both the app and the key. 2. Removed the larswm.run_dialog options, as they are now redundant. 3. Changed the way the larswm.badclass, toolclass and notileclass options work. If the value contains a tilde (~) then in addition to checking if the class equals the value, it also checks for if the class equals what's before the tilde and the instance equals what's after the tilde. An example, to associate all of netscape's download windows with the untiled subdesktop, do this: larswm.notileclass[0]: Netscape~Download 5.1b3 - Jul 19, 2000: 1. Changed the way it deals with XConfigureRequest events. They do not trigger a retile event by themselves anymore. If one of your windows seem to get itself out of place, try using the 'Re-Tile All Now' menu entry on the right mouse button. The reason for this change is that some apps (Netscape is one) seem to be trying to resize itself until it succeeds, basically locking the window manager up with configurereqs. If Netscape opens a new browser window with a set size and position, it doesn't deal well with being unmapped either. I suggest not moving to a new desktop until you've closed all netscape secondary windows. Also, having a larswm.badclass entry for Netscape helps, as Netscape lies about the user selecting the size and position of the window, making it look like a tool window to larswm. After trying various ways of dealing with this, I can only conclude that Netscape is not being a polite client, in that it doesn't let the window manager decide where and when to map its windows. 5.1b4 - Jul 20, 2000: 1. Added the larswm.default_notile and larswm.dotileclass[] options. If default_notile is true, then all new windows are placed in the untiled desktop, unless their class/instance has been specified with a dotileclass line. This can be good if you use alot of non tiling friendly apps. 5.1b5 - Jul 20, 2000: 1. If you hold down Shift while left-clicking a window that does not have focus, it will get focus even if its hints suggested it does not want focus. This is useful if you use Xnest. 5.1b6 - Jul 20, 2000: 1. Removed the automatic determination of tool status. Nothing will be treated as a tool window unless its class/instance has been specified with a larswm.toolclass[] entry. This will in the end make for more predictable behaviour with bad apps that lie about USPosition. 2. Removed the larswm.tile_tools option. 3. Removed the larswm.badclass[] option. 4. Changed default_notile to True, as I believe this to be a better way to do things. For the old behaviour of tiling every window by default, put larswm.default_notile: False in your .larswm. 5. When a window is opened on the untiled desktop, whether you need to manually place it or not is decided like this: If auto_retile is ON for the current desktop: * If the window has had its position set by the user, map it there. * If no position has been set, center it. If auto_retile is OFF * If the window has had its position set by the user, map it there. * If no position has been set, let the user place an outline of the window where (s)he wants it to be mapped. 6. Put max number of toolclasses, notileclasses and hidden windows back to 64 by default. 7. Minor tweak to how it unhides windows. Will not look for a hidden window that was unmapped by the virtual desktop functionality. Improves performance with apps that sends maprequests until their window is mapped. 5.1b7 - Jul 21, 2000: 1. Greatly simplified tool handling. Now all tools are automatically assigned to the untiled subdesktop. No need to arrange tiled windows around tools. Tool windows are exactly like any other untiled window, except they have no title bar, they are visible on all virtual desktops and they are always kept on top of the other windows on the untiled subdesktop, except the window that has focus. 5.1b8 - Jul 21, 2000: 1. Changed the display on the title bar to: {#} (#) [#] # T Which lists the number of windows on: {other screens} (hidden) [other desktops] current desktop number and whether you are on the (T)iled or (U)ntiled subdesktop. 2. Added keyboard shortcuts for moving windows on the untiled desktop. Shift+Control + number on keypad puts it in a general area of the screen, 7 = northwest, 8 = north center etc. Shift+Alt + number on keypad moves it 5% of the screen size in that direction. 8 = up, 2 = down, 4 = left and 6 = right. Sun users: This won't work with the standard keyboard mapping. Please see the README file for an example of how to use xmodmap to fix it. 5.1b9 - Jul 21, 2000: 1. Added keyboard shortcuts for zooming windows. By default these: Shift+Alt+keypad Home = Vertical. Shift+Alt+keypad End = Horizontal. Shift+Alt+keypad 5 = Both. (Maximize) These keys are of course configurable like the others. 5.1b10 - Jul 22, 2000:1. Lots of small tweaks to how it handles the tiled and untiled subdesktops, how it reverts back to a window when one closes. No new options, just more logical behaviour. 2. Added the Re-Scan Windows option on the tiling menu. Use this if you get windows that somehow aren't managed by larswm. Some versions of The Gimp will cause this when resizing images. 5.1b11 - Jul 22, 2000:1. Even more fine tuning of the way it handles untiled windows when they are mapped. 5.1b12 - Jul 23, 2000:1. Fixes a small focus problem with multi-head displays. Move Re-Scan Windows menu entry to the larswm menu (exit/restart). 2. Changed title bar status display to show just virtual desktop number and subdesktop (T or U). 3. Fixed minor window focus reverting problem. 5.1b13 - Jul 23, 2000:1. Final focus handling code. When a window closes, reverts back to the last focused window regardless of which subdesktop it was on. If not on same, toggles subdesktops before reverting focus. 5.2 - Jul 24, 2000: 1. Updated README, docs, and bumped version number. 5.2.1 - Jul 24, 2000: 1. Fixed a crashing bug in the window reverting code. 2. Cleaned up code that checks class/instances. 5.2.2 - Jul 25, 2000: 1. Fixed a bug where looking up a window class would fail if there was no instance specified. 5.3b1 - Jul 25, 2000: 1. Split keyboard handling into its own file, keys.c. 2. Added the option larswm.bar, which will enable the status bar at the bottom of the screen. The left portion of the bar contains the title of the focused window. The right end contains this: [0:4] 1:- 2:1 3:- Untiled (1) {4} Which means: Desktop 0 is active, it has 4 windows. Desktop 1 has no windows, 2 has one window, and 3 has none. The Untiled subdesktop is active on the current virtual desktop, and there are one hidden window on this screen, and 4 windows on other screens. 3. Added option larswm.reserve, which will make window tiling leave the specified number of pixels unused at the bottom of the screen. If the status bar is visible, this reserves pixels above the bar. 4. Added option larswm.res_track, which lets you specify which track you want space reserved in, the default is Right and it can be set to Left or Both. 5.3b2 - Jul 25, 2000: 1. Removed a redundant call to draw_tbar(). 5.3b3 - Jul 25, 2000: 1. Added the larswm.auto_reserve option. This is similar to how it used to work, except it reserves space at the bottom of the screen only. This feature is on by default. 2. Mouse clicks on the status bar: Left previous desktop, Right next desktop, Middle toggle tiled/untiled desktop. 3. Made status bar be on by default. To disable, use: larswm.bar: False 4. Tweaked status bar to be as thin as possible. 5. Windows that have south (or southwest/southeast) gravity will gravitate above the status bar. 5.4 - Jul 25, 2000: 1. Version changed to 5.4 stable. 5.4.1 - Aug 2, 2000: 1. When centering windows on the untiled desktop, the top of the window will never be above the top of the screen. 2. Fix a small typo on prefs.c 3. Added option larswm.stickyclass[] which makes windows of the specified class sticky, that is they are visible on all virtual desktops. 4. Added option larswm.sticky_notile which makes all windows on the untiled subdesktop sticky by default. 5.5b1 - Aug 4, 2000: 1. Added the Zoomed layout option. This arranges the tiled subdesktop so the active window is taking up most of the screen, on top of the others, while the rest are tiled underneath in the same way that the Balanced layout works. 5.5b2 - Aug 4, 2000: 1. Removed Zoomed layout option. Not really useful in practice, and features for no other reason than feature count will not be tolerated. :) 2. Following the same logic, window title bars are gone, since their functionality is better handled by the status bar. Removed larswm.titles option. 3. Changed the status display on the bar slightly. The letters between the <> means: T = tiled active, U = untiled active A = auto tiling on, R = tile resizing on, S = skip focus on. Layouts: d = Default, s = Square, b = Balanced. Also put the window title at the left end of the bar. 5.5b3 - Aug 5, 2000: 1. Added option larswm.lazy_notile, which will make the untiled subdesktop use a lazy focus follows mouse scheme. This can also be toggled from the Control menu (Control+Right mouse click). Also added the letter 'L' to the status bar display between <>. This indicates whether lazy_notile is on for the current virtual desktop. 2. Added the Control+Alt+Left mouse click, which will just raise the selected window without changing focus to it. It can be used on the active window if in lazy_notile mode as a way to bring a window to the front, since a window is not raised automatically when the mouse enters it and gives it focus. This all applies to the untiled subdesktop only. 3. Added two new keyboard shortcuts: Control+Alt+z hides the current window. Control+Alt+w closes the current window. 4. Made all parts of the status bar visible at all times. A '-' in a position signifies "off" or "0". 5.5b4 - Aug 5, 2000: 1. Fixed a crashing bug in the lazy focus code. 2. Control+Alt+x unhides the last hidden window. 5.5b5 - Aug 6, 2000: 1. A few tweaks to focus and subdesktop handling when mapping windows. It should now act in a more useful way when non-input windows like ghostscript opens. 5.5b6 was thrown out. 5.5b7 - Aug 7, 2000: 1. Fix for shortcut keys for desktops and applications when they would use the same key but different modifiers. 2. Added a note in the README about mode lock keys and how they must be off when using larswm shortcuts. This is a known issue that hopefully will be fixed some day. 5.6 - Aug 7, 2000: 1. Made the Shift-Alt-Button1 be a toggle instead of always raising the window. It will now raise a window unless the window is already on top, in which case it will lower it instead. 2. Changed version to stable 5.6. 5.6.1 - Aug 10, 2000: 1. Do not automatically revert focus to tool windows. 5.6.2 - Aug 12, 2000: 1. Fixed a bug where it would retile when using keyboard shortcuts to select next and previous window even if skip_focus was on. 5.6.3 - Aug 21, 2000: 1. Simplified window mapping. Now does not require user interaction with the mouse before mapping a window. A window that has not had its position set will be centered on the screen. 2. Fixed a minor bug where windows would not retile when unhiding a tiled window using the keyboard shortcut. 5.6.4 - Aug 27, 2000: 1. Changed the status bar a bit. gprof showed alot of time spent in sprintf, so all those calls were removed, and the display simplified. It now looks like this in the lower right corner: ----------------------------+ Desktop Name | ----------------------------+ Where the new item is 'H', which is there if there are hidden windows on this screen. 2. Desktops can be named! By default they are labeled Zero, One, Two etc. but this can be changed with the larswm.dtname[][] option. Same rules apply as for the other [][] indexed resources, that is first index is screen, second is desktop. 5.6.5 - Aug 28, 2000: 1. Now sets input focus on a screen when the mouse pointer enters a window on it, if that screen does not already contain the window with input focus. 5.6.6 - Aug 29, 2000: 1. Simplified the way it fetches the next event. This seems to make it a bit more stable when dealing with lots of events, like holding down the 'next desktop' key for example. Removed the getevent() function from main.c and use XNextEvent directly in event.c. 2. Moved a call to initkeys() so it is only called once when a window is first managed. 5.6.7 - Aug 30, 2000: 1. Removed the larswm.auto_retile[][] option, since it is obsoleted by the untiled subdesktop. 2. Removed all code dealing with auto_retile being on or off. Now assumed on for all desktops. 3. Changed the way windows are hidden when switching virtual desktops. Now they are not actually unmapped, but instead moved outside the visible screen area. 4. Made lazy focus on the untiled subdesktop be on by default. 5. Only update the status bars when needed. This also improves performance when dealing with lots of events. 6. Mode flag display now shows: Resize on/off, SkipFocus on/off, LazyNotile on/off, current layout and Hidden Windows menu has entries. 5.6.8 - Aug 30, 2000: 1. Fixed small bug where the status bar would not redraw when the title of the current window changes. 5.6.9 - Sep 1, 2000: 1. Fixed a small bug where the status bar would not be redrawn when it became unobscured. 2. Removed the layout option. Now always uses what used to be called 'Default'. Removed code supporting more than one window in the active track. 3. Control-Alt-Button2 now toggles between tiled and untiled subdesktops. 4. Removed the code for specifying tool space. Now always calculates before retiling. reserve, res_track and auto_reserve options gone. 5.7b1 - Sep 2, 2000: 1. Added the larswm.dtclass[] and larswm.dtnum[] options that let you associate a window class/instance with a virtual desktop number. For example: larswm.dtclass[0]: Netscape larswm.dtnum[0]: 1 would associate Netscape windows with the second virtual desktop. 2. When a window is first mapped, if it wants to be on a different desktop than the current, that desktop is first made active before mapping the window. 3. Fixed a small annoyance with Control-Alt-Button1 where if you lowered a window, you couldn't raise it this way even if a portion was visible. 4. Added the larswm.bar_cmd and larswm.bar_interval options. This will run a command every X seconds showing the first line of output in the status bar. Up to 80 characters will be shown, if you need more, use another process that puts a line, properly scrolled, in a file and cat that file to get the data for the display. They key is to minimize the time that the command larswm runs takes, or the system will feel slow. The external command is responsible for removing any non printable characters, including newline. 5. Yet more improvements to how it handles focus when windows are mapped on the untiled subdesktop when lazy_notile is on. Now it should hopefully "do the right thing" both with transients and secondary non-transients (like 'xv' does). 6. The external command is only run if there are two or fewer events waiting to be processed. This should prevent the wm from being unecessarily slow when dealing with lots of events. 5.7b2 - Sep 3, 2000: 1. Do not change the title bar colors for tiled and untiled subdesktop, instead show 'T' or 'U' and leave it inverted all the time. This makes for a cleaner look I think. 2. Got rid of focus shifting between screens. Was more confusing than useful. Now you have to either use keyboard shortcuts, or select a window on the screen you want to go to. Optional lazy focus follows mouse on untiled subdesktop is unchanged. 5.7b3 - Sep 3, 2000: 1. Changed larswm.bar_cmd to larswm.bar_file. Now reads the first line of a file instead of executing a command. This has two benefits: 1. Hanging command would also hang the wm. 2. This requires no fork/exec in larswm. Included in the tarball and RPM is an example of how to do this in the file sample.barinfo. 5.7b4 - Sep 3, 2000: 1. Removed larswm.bar_file and larswm.bar_interval options. 2. Added support for a FIFO in $HOME/.larswmfifo that is checked once per second for data. Each time up to 80 characters are read, if there are more available in the FIFO, they will be read next time (in one second). No option needs to be specified in .larswmrc as this feature will be automatically used if the FIFO exists. sample.barinfo updated to use the FIFO. 3. Added the -p command line option to specify a different named pipe to use for the status bar FIFO. 5.7b5 - Sep 3, 2000: 1. Minor fix. Now removes leading and trailing spaces and unprintable characters from the status bar message field. 5.7b6 - Sep 3, 2000: 1. Fixes an obscure bug that could make it lock up when unmapping a window. 5.7b7 - Sep 4, 2000: 1. Code cleanup in the way preferences are looked for. You need to change your indexed resources like this: BEFORE: larswm.tile_resize[1][2]: False AFTER: larswm.1.2.tile_resize: False BEFORE: larswm.toolclass[3]: XClock AFTER: larswm.toolclass.3: XClock This requires alot less code to achieve the same result as before, that is, more specific overrides less specific. If you had for instace larswm.tile_resize[][5]: True you should change it to larswm.*.5.tile_resize: True This is basically just using the X resource manager correctly, and I prefer correctness over backwards compatibility. :) 2. I've run ElectricFence on it, and no memory overruns/underruns have been detected so far after fixing one strcpy call in the resource loading code. 3. Minor performance tweak in mouse_on_screen, now spends very little time there on single screen systems. 5.7b8 - Sep 4, 2000: 1. Added a call to setlocale() so non-standard characters should be visible on the status bar. 2. Updated sample.barinfo to show how to get stock quotes from Yahoo and display them on the status bar. 5.7b9 - Sep 4, 2000: 1. Removed the rechecking of hints everytime a window was tiled. Now only checks on PropertyNotify events. 5.7b10 - Sep 4, 2000: 1. Added sample.xsession showing one way to use a background program feeding the named pipe without leaving it running after logging out. 5.8 - Sep 5, 2000: 1. Changed version to 5.8 and updated docs here and there. 2. Changed the status bar maximum message length to 132 characters. 5.9b - Sep 6, 2000: 1. Started to use CVS. Will now release betas by doing a cvs export whenever I think there is enough new stuff for you to test. The version as reported by larswm -v will just say 5.9b until 6.0 is released, but the source tarball will have date and time in the name. 2. Cleaned up menus. Now there is only two, the main menu on Button3, and the list of hidden windows on Button2. 3. Tweaked the way skip_focus works together with Control+Button1 clicks. If skip_focus is off: Button1=Focus+Retile Control+Button1=Focus If skip_focus is on: if tile_resize is on: Button1=Focus Control+Button1=Focus+Retile if tile_resize is off: Button1=Focus+Retile Control+Button1=Focus This should mostly "do the right thing". 4. Raise/Lower is now Alt+Button1. 5. Added show_class on/off to main menu. If on, it will show (class~instance) of the focused window on the status bar. 6. Some more simplification in the prefs loading code. No change in file format though. 7. Lots of tweaking of the focus code. Improvement in previous/next window shortcuts. Now can move focus around without rearranging windows on a skip_focus desktop. Also, you should always find a virtual desktop exactly the way you left it when you go back to it after using another desktop. 8. Cleaned up sample.barinfo a bit. Added some more options. See comments in the script for info on how to set it up. 9. General code cleanup, little details here and there. BETA_5_9_3 10. Fixed a small bug where shift-control-up would not work right after switching desktop. BETA_5_9_4 11. Put the status bar coloring back the way it was so that default is black on white text with black border. 12. When opening a new centered window, and when using keyboard shortcuts to move a window to the north, center or south, make sure that not only the top of the window but also the left edge is always visible. 13. New option larswm.*.*.clickthru. When this is True, clicks used to focus a window are also passed on to the client in some cases. If clickthru is on, the click will be passed in these circumstances: Tiled subdesktop: when skip_focus is on. and no modifier was used. Untiled subdesktop: when lazy_notile is off. Clicks will NOT be passed through if the click forced a change between the tiled/untiled subdesktop, or if either force-focus (Shift) or toggle-retile-after-focus (Control) was used. Button2 and Button3, which normally open menus, will be passed through, but only on the untiled subdesktop, otherwise, you'd have to hunt for those little slivers of root window that shows between tiled windows to use the menus. 14. Once again the mode flag field has been updated to show the new mode, it is now: Tiled subdesktop clickthru tile_resize skip_focus lazy_notile autoraise_notile Hidden Windows Letter means on, '-' means off. BETA_5_9_5 15. Hidden window list moved from Button2 to Shift-Control-Button3. This means if you have clickthru on, you can use Button2 to paste without first selecting the window. Like for Button1, if the window you click on is on a different subdesktop then the currently active, the click will not be forwarded. BETA_5_9_6 BETA_5_9_7 16. Made skip_focus be on by default. If tile_resize is false, windows will move around anyway, unless Control-Button1 is used to select them. After much testing I have found this to be the most efficient setting for me. To get the old retiling on focus change by default, just put larswm.*.*.skip_focus: False in the config. 17. Fixed a bug where if you used the keyboard to move to previous or next window on a skip_focus:on with tile_resize:off desktop, the windows would not rearrange themselves. 18. Got rid of stderr message when the named pipe cannot be found. If it is not there, assume the user doesn't want this feature enabled. BETA_5_9_8 19. Better reverting to previously focused window. Now does the right thing when for instance running ghostscript from a tiled terminal, that is, focus stays with the terminal window that was used to start it. BETA_5_9_9 20. When clickthru is on, always pass clicks on to tool windows regardless of which subdesktop is active. 21. Tool window mapping/unmapping forces retiling. 22. Clickthru on a tile_resize:False desktop now works if the clicked window was already in the left track and no visible retiling occured. 23. More tweaks to focus handling when a window is unmapped. 24. Using any of the zoom keyboard shortcuts on a tiled window will do one of two things: If the window is not in the left track, put it there. If the window is in the left track, swap it with the top right track window. BETA_5_9_11 25. Fixed a bug when using the zoom key to swap the current with the previous left track window. BETA_5_9_12 26. Fixed a bug that prevented autoraise_notile prefs from being seen. BETA_5_9_13 BETA_5_9_14 27. Got rid of lazy_notile and autoraise_notile since the reason they were created no longer exists, and that mode did not integrate well with the rest of larswm. (clickthru gets rid of the need to click twice on windows when you are working with more than one at a time.) 28. On a single screen display, do not grab the keyboard combination for prev and next screen. 29. When unhiding a window, don't lose track of focus if the newly mapped window did not want input focus. 30. Alt-Button3 will now lower a window if that window belongs to the currently active subdesktop, otherwise it will be raised. 31. Compiles without any warnings with gcc -Wall -ansi -pedantic. BETA_5_9_15 32. Fix prev/next screen key bug. BETA_5_9_16 33. Fix small bug introduced in BETA_5_9_15 that didn't redraw the window borders correctly in all cases. BETA_5_9_17 34. Got rid of the alarm() stuff. Now, instead of checking the named pipe every second for updates, it will only check if it receives an XClientMessageEvent on an atom named "LARSWM_MESSAGE". One way to send that message is to run larswm with the 'message' command line argument. So, to use the status bar message facility, write the data to the pipe and then run 'larswm message'. #!/bin/sh # helloworld example echo "Hello World" > $HOME/.larswmfifo larswm message exit 0 It's my hope that getting rid of the signal stuff will make it a bit more stable, and it also makes sense that the supplier of the data decides the rate at which it should be fetched. 35. Added the flushmessage command line option which tells the running larswm to read and throw away everything in the pipe. It's a good idea to use this before writing to the pipe to make sure the message you are about to write to the pipe will be seen right away. sample.barinfo have been updated to use this new message facility. In the helloworld example above, you would insert the line 'larswm flushmessage' before the line containing the echo command. BETA_5_9_18 36. Fix a bug where focus would not be set to the left track on tile_resize:false desktops. BETA_5_9_19 37. Excerpt from IRC: my recommendation as le grande artiste is to use [ instead of < Let it be known that I have now done this years' change of larswm purely for looks. :) BETA_5_9_20 38. Got rid of Alt+Button3 for Raise/Lower. If a window is in the way, it makes more sense to use the keyboard shortcut to hide it, do stuff to whatever was underneath, and then use the keyboard shortcut to unhide the last hidden window. 39. Shift+Button3 now shows the list of hidden windows if there are any. 40. NO mouse grabs are done on the focused window. This means all modifier combinations on clicks are available to the application. BETA_5_9_21 41. Minor focus tweaks. prev/next_window on the untiled subdesktop was sometimes confused. BETA_5_9_22 42. Added keyboard shortcuts for resizing windows on the untiled subdesktop. The default keys are: Shift-Control-Alt-KP_Up Grow vertical Shift-Control-Alt-KP_Down Shrink vertical Shift-Control-Alt-KP_Right Grow horizontal Shift-Control-Alt-KP_Left Shrink horizontal Shift-Control-Alt-KP_Home Grow both ways Shift-Control-Alt-KP_Up Shrink both ways It will not let any part of the window end up outside the visible screen area, and it will honor all hints, including minimum size. REL_6_0_0_PRE_1 43. Put a delimiter between restart and exit to avoid accidents. =) REL_6_0_0_PRE_2 44. Do allow Button3 clicks on inactive windows to be sent to the client if the window is an untiled window and the untiled desktop is active. Basically, to use the menu you need to Button3 click in one of the following locations: 1. The root window 2. Any inactive tiled window. 3. An inactive window that is not a tool and that is on a different subdesktop than what is currently active. REL_6_0_0_PRE_3 6.0 - Sep 11, 2000: 1. Change version to 6.0 stable. Update docs. REL_6_0_0 6.0.1 - Sep 13, 2000: 1. Fix a bug in status bar messaging that would coredump if a message containing just a newline was in the pipe when updating the bar. This changes slightly how the message is displayed, no editing is done by larswm, so it is the responsibility of the data source to strip out newlines and other non-printable characters. Also, if there is no message in the pipe, the status bar message will be cleared instead of showing the old message when 'larswm message' is run. 2. In sample.barinfo, remove dependency on wget for the BSDs. REL_6_0_1 6.0.2 - Sep 13, 2000: 1. Restore the functionality that moves focus between screens when the mouse is moved into a different screen. Implemented slightly different than before, mouse pointer does not have to enter a client window, entering the screen is enough. 2. Fixed a real small bug in the layout of tiled windows. One pixel was wasted between status bar and the windows. =) REL_6_0_2 6.0.3 - Sep 16, 2000: 1. Fix the bug that would make the root window get the same background color as the menu in some instances when right clicking and releasing quickly. Thanks to Michael Lothian for finding a solution to this problem. 2. Added the larswm.show_class option which lets you turn on showing the window class on the status bar on startup. 3. Added the larswm.floatclass.# option which lets you specify certain windows you always want floating above the other tiled and untiled windows. Like tools, mouse clicks are passed on to these windows if clickthru is on regardless of which subdesktop is active. REL_6_0_3 6.0.4 - Sep 16, 2000: 1. Got rid of larswm.default_notile option. Now always on, that is, no window is tiled unless a larswm.dotileclass.# line exists for its class/instance. REL_6_0_4 6.1b - Sep 21, 2000: 1. Got rid of larswm.bar option. Status bar is now always visible, as it has other functions not available without it. 2. Added larswm.toggle_inc_key and mod shortcut. This lets you toggle whether move/resize keys does 5% of screen size or 1 pixel (or if hints are specified, the smallest possible change.) When resizing, it actually resizes 2 pixels instead of 1, to make the window stay where it is. 3. A 'B' in the mode flags on the status bar means the 5% change is in effect. 4. When show_class is on, show class info about the focused window after the class/instance name in a separate mode flag field. [nftsi] n = notile, f = floating, t = tool, s = sticky and i = takes input. 5. Cleaned up menu code, but did not remove it. Moved hidden windows back to where 9wm keeps them, that is at the end of the main menu. The menu is now exactly 9wm standard. 6. Added many mouse commands to the status bar, they are now: No modifier Button1 Previous desktop Button2 Toggle tiled/untiled Button3 Next desktop Button4 Previous desktop Button5 Next desktop Shift Button1 Toggle clickthru Button2 Toggle tile_resize Button3 Toggle skip_focus Button4 Previous window Button5 Next window Control Button1 Toggle show_class Button2 Toggle focused isnotile Button3 New Terminal Shift+Control Button1 Toggle focused isfloat Button2 Toggle focused istool Button3 Toggle focused issticky The mouse wheel functions also works when the pointer is on the root window or above an unfocused window. 7. Removed the larswm.show_class option as it is now very quick and easy to turn that feature on by control-button1 clicking the status bar. BETA_6_1_0 8. Removed grab.c! Removed menu code! 9. The way to find and unhide hidden windows are as follows. On the status bar, these new mouse clicks: Alt-Button1 Show previous hidden window Alt-Button2 Unhide currently shown window Alt-Button3 Show next hidden window Alt-Button4 Show previous hidden window Alt-Button5 Show next hidden window The mouse wheel functions also work on the root window and any unfocused window. When a hidden window label is shown instead of the currently focused window's label, it looks like this: Hidden (xterm) And if the window is on a different screen than the status bar you are looking at: Other (xterm) If no hidden window is shown when Alt-Button2 is pressed, the currently focused window will be hidden. BETA_6_1_1 10. Get rid of debug printf in buttons.c. BETA_6_1_2 11. Dont show focused window's class info while browsing hidden window labels. BETA_6_1_3 12. Added the larswm.selection.# option. Use this in conjunction with application shortcuts to define applications that will have the current selection inserted into the command line where the first '%s' occurs before executing. Here is an example: larswm.application.0: xterm -e man %s larswm.selection.0: True larswm.application_key.0: m larswm.application_mod.0: Shift+Control With that, you can highlight text and when using the hotkey, an xterm with a manual page about whatever word you highlighted will open. See sample.larswm for more examples. BETA_6_1_4 13. Changed the way the selection is passed to apps. When the app is launched, the following variables will be set: LARSWM_SELID=window id of selection owner LARSWM_SELNAME=title of selection owner LARSWM_FOCUSID=window id of focused window LARSWM_FOCUSNAME=title of focused window LARSWM_SELTEXT=highlighted text. Up to 1024 characters of the selection. The reason for both selection owner and focused window is that when you want to get the title of a window, the title is almost never set on the same window as selection owner is reported as. See sample.larswm for an example of how to set up various application hotkeys using these variables. 14. Got rid of the larswm.selection option, the environment varible is always set if text exists. 15. Added the file sample.editor which shows how you can use the variables to pass current working dir of a terminal window to the launched app. BETA_6_1_5 16. Fix a portability problem with putenv. BETA_6_1_6 17. Set focused window id/name variables even if nothing is selected. 18. Variables are no longer set to the empty string but left unset if that particular bit on info is not available (most often LARSWM_SELNAME). BETA_6_1_7 19. Updated sample.editor to be a bit smarter. BETA_6_1_8 20. Added mouse move and resize. You initiate a window move by Shift-Alt-Button1 clicking the status bar. This warps the pointer to the top left corner of the currently focused window, and the window will be dragged until you release Button1. To resize, Shift-Control-Alt-Button1 click the status bar. This warps the cursor to the lower right corner of the window, and that corner will be dragged until you release Button1. Please note that the display will be grabbed during window/corner dragging and no content will be updated. This prevents a flood of expose events to the clients while you are manipulating the window. BETA_6_1_9 21. Added display of geometry on the status bar while moving and resizing with the mouse. BETA_6_1_10 22. When starting to move or resize a window with the mouse, make sure that window is on top. BETA_6_1_11 23. To limit the number of key combinations, the keys for resizing the left track has been removed. Instead use the same keys that you use for resizing a window on the untiled desktop: Shift-Control-Alt-KP_Right Grow Shift-Control-Alt-KP_Left Shrink Shift-Control-Alt-KP_Up Maximize Shift-Control-Alt-KP_Down Restore This functionality is available when the tiled subdesktop is active, when the untiled subdesktop is active, these keys resize the focused window like before. BETA_6_1_12 24. Update docs. Up version to pre-release status. REL_6_2_0_PRE_1 25. All shell variables that are set when launching an app have been renamed to just WM_something. 26. Added the WM_SELICONNAME and WM_FOCUSICONNAME which contains the icon title property of the windows. The complete list is now: WM_SELTEXT=highlighted text. WM_SELID=window id of selection owner WM_SELNAME=window title of selection owner WM_SELICONNAME=icon title of selection owner WM_FOCUSID=window id of focused window WM_FOCUSNAME=window title of focused window WM_FOCUSICONNAME=icon title of focused window 27. Changed the way text messages are sent to be displayed on the status bar. Now communicates entirely through the X server. 28. Removed the flushmessage command line option. 29. Changed how 'larswm message' works. Now takes the text to be displayed as an argument, if no argument is included, clear the status bar. larswm message "Hello World" REL_6_2_0_PRE_2 30. Forgot to update sample.barinfo, now uses the new message facility. REL_6_2_0_PRE_3 7.0 - 9/25/2000: 1. Upped version to 7.0 as this contains quite a few changes that makes it incompatible with previous config files etc. REL_7_0_0 2. Fixed two memory leaks. REL_7_0_1 3. Fixed a big where WM_NAME shell variables would not be set. REL_7_0_2 4. Removed server grabbing when moving and resizing windows with the mouse. REL_7_0_3 5. Simplified message sending. Each "larswm message" run involves fewer function calls in the running larswm. REL_7_0_4 6. When using the mouse to move or resize, after manipulating the window, restore the mouse pointer back to where it was when the command was initiated. 7. Added the option larswm.button#.application, This will run a command when the mouse is clicked outside any window. Since it can be hard to aim at the visible areas of the root window when the screen is full of tiled windows, the window borders can also be used for this purpose, making it easy since all you have to do is move the mouse against the left, right or top edge of the screen before clicking. Example: larswm.button3.application: xterm will launch en xterm when right-clicking the desktop. The same environment variables are set as for keyboard shortcuts, letting you define mouse commands that behave differently depending on what you are doing. 8. Fixed a bug where focus would move when going to another virtual desktop and back again. 9. Added sample.barclock, which is just the date/time display portion of sample.barinfo. 10. Alt-Button1, 2 and 3 on the status bar used for finding and unhiding/hiding windows also works on the root window. REL_7_0_5 11. Oops. Forgot to add sample.barclock to the RPM spec file. 12. Got rid of larswm.terminal option, use keyboard shortcuts and/or mouse button apps to emulate the old behaviour. 13. The key Shift+Control+Return is no longer defined by default. 14. Control-Button3 on the status bar zooms/unzooms the focused window. REL_7_0_6 15. Fix a small typo in the -defaults output. 16. Add a reference card for the resources, larswmrc_refcard.ms, which is a troff/tbl document like the other reference cards. 17. Fix border clicking so that it works on inactive borders as well. Now you really can put the mouse against an edge and click to execute mouse applications. REL_7_0_7 18. Fix the problem where sometimes clicks would work as if they were on the root window or the border even if they were inside the window. This problem only showed up with clients who did not select mouse clicks on all of the window, and left some areas exposed to clicks that it wasn't interested in receiving. An example is Xcalc, between the buttons. REL_7_0_8 19. Removed some old code dealing with FocusIn events that could cause a core dump in some rare circumstances. 20. No longer sets a cursor. To get the old cursor back, use: xsetroot -cursor_name top_left_arrow in your .xsession or other login file. The special move and resize cursor are still set when those operations are performed. 21. Minor tweak to status bar. Saves 2 pixels in both dimensions by droping the border. 22. Fix a minor visual bug where windows sometimes would not line up properly with the status bar when different border widths and tile padding was chosen. REL_7_0_9 23. Removed all the different mouse combinations on the status bar. 24. Added a menu for the status bar, that works the same way that you find and unhide windows. Use Control + mouse buttons on the status bar to access the menu. 25. Got rid of larswm.border and larswm.tile_pad options. If you don't want 2 pixel borders and 1 pixel padding, edit dat.h (Look for BORDER and TILE_PAD at the top of the file.) 26. Got rid of larswm.sticky_notile option. 27. Made tools be floating by default. REL_7_0_10 28. Fixed a focus bug that was most noticable in Netscape, where sometimes you could click in a text field to select it, but no keystrokes would make it there. REL_7_0_11 29. Added the larsremote program, which contains only the code needed to send messages to larswm. It can send exit, restart and status bar message events. 30. The exit, restart and message command line arguments are no longer supported by the main larswm program, use larsremote. 31. Added the larsclock program, which is a clock app that keeps the status bar updated without launching an external program to send the message to larswm. REL_7_0_12 32. Removed a call to abort() in client.c, this was the only reported crash since 7.0.12, and I don't think anything will break by just having it silently ignore that particular error condition. 33. Made it possible to define keyboard shortcuts with no modifiers. Specify 'None' as modifier. 34. Fixed an omission, larsremote now correctly sets an exit status of 0 if it ran without problems. REL_7_0_13 Dec 1, 2000. 35. Fixed a memory leak in larsclock. 36. Removed checking for input hint. Many programs set this incorrectly, and I have yet to see anything break by giving input focus to a window that didn't ask for it. This also means force focus (shift-click) is gone. 37. Fixed sample.editor to work with RH72 default prompt format. REL_7_0_14 May 2, 2002. 38. Fixed a bug where, depending on what modifiers were used, keystrokes would just get eaten by larswm and not passed down to the appplication. REL_7_0_15 Jun 7, 2002. 39. Added another way to zoom non-tiled windows. By default Shift-Control-space zooms a window so it uses 90% of the screen height and 60% of the width and centers it. In larswmrc, edit: larswm.move_select_key: space larswm.move_select_mod: Shift+Control to chose keyboard command. Also, Control-Button1 on an inactive untiled window gives it focus and select zooms it in this way. Shift-Control-Button2 in status bar is another way to toggle select zoom on a window. Note that when zooming a window, if another widow is already zoomed, it will be unzoomed. 40. With mouse pointer on status bar, if holding down Shift while rolling the mouse wheel you will go to prev/next window on current desktop. Shift-Control and wheel will shrink and grow current window. Shift-Control and Button1/Button3 also shrinks/grows. Control-Shift-Alt and wheel will move window vertically, while Shift-Alt and wheel moves it horizontally. REL_7_0_16 Jun 28, 2002. 41. Fixed a small bug in the focus handling when using the select zoom feature mentioned in entry #39 above. 42. Removed a couple of obsolete doc files. 43. If a .larswmrc cannot be found in the home directory, or where the user specified with -f then a system wide file is looked for. By default /etc/X11/larswmrc is loaded. REL_7_0_18 Jul 1, 2002. 44. When using the keyboard or mouse to go to the previous or next window on the untiled desktop, if the current window is select zoomed, the next/previous window is select zoomed too. Also, if a window is zoomed the normal way and you try to select zoom it, it is first unzoomed. To recap: Only one window can be select zoomed at any given time. More than one window can be zoomed vertically, horizontally or both (maximized) at a time. A window can only have one type of zoom active at any given time. I believe these rules will make for less confusion on the long run. 45. When unhiding a window, properly set the active subdesktop to whichever the unhid window belongs to REL_7_0_19 Jul 6, 2002. 46. Simplified zoom select to not be too automatic, it is the untiled subdesktop after all. You can have more than one window zoomed in the middle. When you go to next and previous windows using the keyboard or mouse the newly focused windows are not automatically zoomed. Also making sure that a window that has one kind of zoom applied is first unzoomed when another tpe of zoom is requested. Also made this kind of zoom use the full height of the screen and adjust width so the ratio is the same as for a US letter sized paper (11x8.5). REL_7_1_0 Jul 10, 2002. 47. Only one very small change in this patch, when resizing a window using the mouse wheel, rolling up will grow the window and rolling down will shrink it. REL_7_1p1 Jul 18, 2002. 48. raise_notile_key and raise_notile_mod were omitted from "larswm -defaults", this has been fixed. Also, version numbering back to old standard. REL_7_1_2 Jul 21, 2002. 49. Added keyboard shortcut for moving a window between the tiled and untiled subdesktop. As a result, removed that functionality from the control menu. Default key binding is Shift+Control+space When a window is changed from being tiled to untiled, it is sized to 1/2 screen height and width and centered on the screen. REL_7_1_3 Aug 22, 2002. 50. By Florian Forster Partial rewrite of the tiling code. The behavior stays the same, but a PResizeInc-hint does no longer result in (ugly?) gaps between windows and/or tracks, ConfigureNotifies are sent at more appropriate times and a simple debug-message system has been implemented. (Thank you Florian, this looks much nicer! /Lars) REL_7_1_4 Aug 23, 2002. 51. Added the option to compile it with 3D borders. This is on by default, edit Imakefile to turn off. The reason it is not a runtime option is, some people might not want all that extra code that does nothing except make it look pretty linked into their binaries. With this, if you do not specify colors in your .larswmrc, you get my default color scheme, yellow on slategray. BETA_7_2_0 Sep 10, 2002. 52. Fixed a redrawing problem. When moving or resizing with the mouse, the 3D borders would get smudged. 53. Bug when xterms will open up thinking they are 80x24 even though they've been tiled to other sizes is still there. Help wanted to find this. :) BETA_7_2_1 Sep 10, 2002. 54. Some code cleanup, removed unnecessary calls to sendconfig(). 55. Window gravity should now be accurate. 56. Released with known xterm size problem. Workaround documented in README and manpage. In short, put this line in your .cshrc or .bashrc: eval `resize` 57. Incorporated the users manual into the main larswm manpage. REL_7_2_2 Sep 11, 2002. 58. Oops! Cleaned out a bit too much. Put some sendconfig calls back. Now drop down menus and stuff like that shouldn't appear in the wrong location after a window has been moved by larswm. REL_7_2_3 Sep 12, 2002. 59. To switch virtual desktop with the mouse wheel, the pointer needs to be on the status bar. Also, when rolling the wheel above an inactive window, that window will be made active and receive the Button4/Button5 events. This should prevent the annoying behaviour when you flip through desktops with the wheel, only to have it get stuck on a window that happen to be under the mouse pointer after you switch desktop, and also be consistent with how the normal 3 mouse buttons work. 60. Small tweak to how default colors are handled when compiled with THREE_D on. 61. Always show Class~Instance and window flags on status bar. 62. When a window is moved from the tiled to the untiled subdesktop, the hints are checked for its default size and location. REL_7_2_4 Sep 27, 2002. 63. Item 62 rolled back. Too many clients do not set proper hints. REL_7_2_5 Sep 28, 2002. 64. Small fix to virtual desktop switching. Should work with transparent aterm windows now. REL_7_2_6 Sep 29, 2002. 65. By Florian Forster A window's title which is too long for larswm's bar is now chopped appropriate. 66. Fixed a long standing bug where the root window would be repainted with larswm's current background color when some GTK applications were closed. 67. Fixed another long standing bug where new apps could not be launched after certain GTK apps had been running for awhile, most notably Galeon. REL_7_2_7 Oct 26, 2002. 68. Fix #67 did not work. Removing all that selection stuff for now. This means the special shell variables (WM_SELTEXT etc) are no longer set. REL_7_2_8 Oct 26, 2002. 69. Changed the default session file to run ssh-agent if it is available. RPM version upped to 7.2.8-2, no change to source file version. REL_7_2_8 Oct 31, 2002. 70. Changes to default config files to update them for RedHat 9. (Using Mozilla instead of Galeon etc) 71. Removed some unused code. 72. When specifying Class~Instance, if you do not include both (using the tilde), your string is compared both to class and instance of the client. REL_7_2_9 Apr 3, 2003. 73. Applied patch from debian bug database that adds a -format option to larsclock. Changed the default format to be 12 hour clock. 74. Applied patch from Edelhard Becker to fix focus problem with GTK2 applications. REL_7_2_10 Apr 28, 2003. 75. Added the concept of setting aside windows using a keyboard shortcut. 76. Added the 'z' indicator to the status bar. On when a window is in a zoomed state. 77. Some tweaking to window/status bar layering. Should work a tad better with windows that are bigger than the area above the status bar. REL_7_3_0 Apr 3, 2004. 78. Swapped the meaning of wheel up and down when resizing windows. Think of it as moving the window closer to your eyes when rolling the wheel towards you. 79. Added mouse combos for setting windows aside. Hold Control-Alt and click status bar to do the following: button1 = put back next window button2 = put aside or put back button3 = put aside current window button4 = button1 button5 = button3 80. Fixed window stacking. When using Control-button1 to select a window, never change stacking if selecting a window on the inactive subdesktop. For ghostscript without frontend and similar situations. REL_7_3_1 Apr 5, 2004. 81. Fixed 3D borders. Now uses 0 width lines for the effect. The result is a slightly cleaner look and possibly faster drawing on some X servers. REL_7_3_2 Apr 15, 2004. 81. Fixed crashing bug when using Shift-wheel-up on the status bar of an empty virtual desktop. REL_7_3_3 Apr 30, 2004. 82. Added one more way to zoom a window, similar to the Shift-Alt-KP_Begin used to maximize a window both ways. Using Shift-Control-Alt-KP_Begin will make the window as close to the exact size of the display as possible while still following the size hints. REL_7_3_4 May 5, 2004. 83. Made windows that are set aside be stacked along the right edge the same way tiled windows are in the right track when resize is off. 84. Very minor fix to mouse resizing, making the window corner follow the mouse pointer better. 85. Tweaked how windows are sized when moved from tiled to untiled subdesktop. Now uses size hints if appropriate. REL_7_3_5 May 7, 2004. 86. Applied Tommy Pettersons sticky-space-per-desktop patch, as found in the 7.3.5 Debian package. REL_7_3_6 May 15, 2004. 87. Applied a couple of Mikolaj Golub's patches. Fix for crashing bug when using xxkb. Small tweak that lets you cycle through windows in the right track the same way whether tile_resize is on or off. REL_7_3_7 May 16, 2004. 88. Restored the zoom_full_ entries to prefs.c. 89. Updated email address and website info with new permanent addresses. Thanks to dyndns.org they should stay permanent from now on. Please update in your packages if you provide larswm binaries of any kind. REL_7_3_8 May 20, 2004. 90. Added a way to quickly move a window to a different virtual desktop. It is not exactly like Mikolaj Golub's patch set, but a variant of it. If you use Shift-Alt with Left or Right arrow keys, you switch desktop while dragging the focused window with you to the new desktop. REL_7_3_9 May 25, 2004. 91. Removed the special handling of transient windows. They are now just forced to the untiled subdesktop. This should make it easier to deal with things like Mozilla download windows. 92. Ran all source code through GNU Indent. 93. Cleaned up manual pages, README etc. removing most of the information, since it will be part of the new User Guide instead. 94. Added Arnold Robbins' 9menu-1.7 to the dist. Renamed it to not cause conflicts when installing both larswm and 9menu, and to comply with the 9menu license when modifying the code. The menu items were made much larger so as to require less mouse precision. Only one menu will be allowed on each display at a time. Also updated sample.larswmrc to use the menu. 95. Cleaned up gravity code again. It is verified to work correctly with xterm, xcalc, xlogo, xedit and a few other standard X programs. It may leave windows slightly off or in from screen edges with clients that do not set geometry hints properly. REL_7_4_0 May 30, 2004. 96. Ignore mouse wheel in menu. 97. Updated the manual pages. REL_7_4_1 May 30, 2004. 98. When using the menu, Escape closes it. **** Thanks to Florian Forster for 99-101. :) 99. Cleaned up some inconsistensies in the status bar menu. 100. Removed the automatic association between tile_resize and skip_focus. sample.larswmrc has been updated to reflect this. Basically you need to have both tile_resize: False and skip_focus: False to get the old behaviour. 101. Fixed a small bug with window focus when using sticky windows on the tiled subdesktop. REL_7_4_2 May 31, 2004. 102. Fixed the XMULIB reference in the Imakefile. 103. Restored manual page. Who knows when I'll have tiem to finish the new manual. :/ REL_7_4_3 Jun 01, 2004. 104. Made the menu window sticky in the default config so you don't have to search for it if you try to open more than one menu. REL_7_4_4 Jun 01, 2004. 105. Fixed RPM spec session file name. REL_7_4_5 Jun 02, 2004. 106. Updated manual page. Incorporated keyboard and mouse tables. 107. Removed RPM spec file from source dist. This will make it easier to provide RPMS for other distros, and remove the need for a new source dist when the RPM build changes. SRPM files will be made available instead. REL_7_4_6 Jun 02, 2004. 108. Final (I hope!) cleanup of the focus code when using Control-Button1 to change the default focus rules. REL_7_4_7 Jun 03, 2004. 109. Repackaged tar file, upped version to not have any checksum confusion. REL_7_4_8 Jun 03, 2004. 110. Fixed a rare bug where the status bar would not get redrawn when changing virtual desktop. 111. Removed a couple of unused functions. 112. Status bar made slightly thinner when using 3D borders. 113. Changed section of man pages to follow Debian standards. REL_7_4_9 Jun 16, 2004. 114. Added the Shift-Control-0 keyboard command to set aside all untiled windows except the currently focused. 115. Control-Button1 on an aside window will put it back, then put aside all other untiled windows. 116. Fixed a bug where the wrong subdesktop could be active after putting back an aside window. 117. Made the menu slightly wider and shorter. 118. Don't count tool space on a desktop where tile_resize is off. 119. A tool window should never get focus except when manually focused by clicking on it. Note that focus will still be removed from the currently active window when a tool window opens. REL_7_5_0 Jun 17, 2004. 120. Shaped windows did not resize correctly when using the mouse. REL_7_5_1 Jun 21, 2004. 121. Applied patches supplied by Tommy Petterson. Fixes a couple typos, makes larsclock use locale, easier to configure larsmenu padding. 122. Removed some old junk from the Imakefile, and cleaned out the tabs that broke BSD make. REL_7_5_2 Jun 28, 2004. 123. Tweaked how colors for 3D borders are calculated. 124. Fixed menu inconsistency in sample.larswmrc. REL_7_5_3 Jul 15, 2004. larswm-7.5.3/client.c0000644000000000000000000001213210065667625014427 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" Client *clients; Client *current; Client *prev_current; void setactive (Client * c, int on) { if (!c || (c->parent == c->screen->root)) { nofocus (); return; } if (on) { XUngrabButton (dpy, AnyButton, AnyModifier, c->parent); XSetInputFocus (dpy, c->window, RevertToPointerRoot, CurrentTime); cmapfocus (c); } else { XUngrabButton (dpy, AnyButton, AnyModifier, c->parent); XGrabButton (dpy, AnyButton, AnyModifier, c->parent, False, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeSync, None, None); } draw_border (c, on); } void draw_border (Client * c, int on) { #ifdef THREE_D GC topshadegc; GC botshadegc; #endif if (!c) return; if (c->parent == c->screen->root) return; XSetWindowBackground (dpy, c->parent, on ? c->screen->black : c->screen->white); XClearWindow (dpy, c->parent); #ifdef THREE_D botshadegc = on ? c->screen->botblackgc : c->screen->botwhitegc; topshadegc = on ? c->screen->topblackgc : c->screen->topwhitegc; XDrawLine (dpy, c->parent, botshadegc, 0, (2 * BORDER) + c->dy - 1, (2 * BORDER) + c->dx - 1, (2 * BORDER) + c->dy - 1); XDrawLine (dpy, c->parent, botshadegc, (2 * BORDER) + c->dx - 1, (2 * BORDER) + c->dy - 1, (2 * BORDER) + c->dx - 1, 0); XDrawLine (dpy, c->parent, topshadegc, 0, 0, (2 * BORDER) + c->dx - 1, 0); XDrawLine (dpy, c->parent, topshadegc, 0, 0, 0, (2 * BORDER) + c->dy - 1); #endif } void active (Client * c) { int i; if (!c) return; if (c == current) return; if (current) { setactive (current, 0); if (current->screen != c->screen) cmapnofocus (current->screen); } setactive (c, 1); if (current) prev_current = current; current = c; for (i = 0; i < prefs.desktops; i++) { if (current->screen->notilefocused[i] == current) current->screen->notilefocused[i] = 0; if (current->screen->focused[i] == current) current->screen->focused[i] = 0; } if (!current->istool) { if (current->isnotile) current->screen->notilefocused[current->screen->desktop] = current; else current->screen->focused[current->screen->desktop] = current; } update_tbar (); } void nofocus (void) { static Window w = 0; int mask; XSetWindowAttributes attr; if (current) { prev_current = current; setactive (current, 0); cmapnofocus (current->screen); } current = 0; if (w == 0) { mask = CWOverrideRedirect; attr.override_redirect = 1; w = XCreateWindow (dpy, screens[0].root, 0, 0, 1, 1, 0, CopyFromParent, InputOnly, CopyFromParent, mask, &attr); XMapWindow (dpy, w); } XSetInputFocus (dpy, w, RevertToPointerRoot, CurrentTime); update_tbar (); } void top (Client * c) { Client **l, *cc; l = &clients; for (cc = *l; cc; cc = *l) { if (cc == c) { *l = c->next; c->next = clients; clients = c; return; } l = &cc->next; } } Client * getclient (Window w, int create) { Client *c; if (w == 0 || getscreen (w) || getbarscreen (w)) return 0; for (c = clients; c; c = c->next) if (c->window == w || c->parent == w) return c; if (!create) return 0; c = (Client *) malloc (sizeof (Client)); memset (c, 0, sizeof (Client)); c->window = w; /* c->parent will be set by the caller */ c->parent = None; c->reparenting = 0; c->state = WithdrawnState; c->hidden = 0; c->iszoom = ZOOM_UNZOOMED; c->isaside = 0; c->isleft = 0; c->init = 0; c->cmap = None; c->label = c->class = 0; c->ncmapwins = 0; c->cmapwins = 0; c->wmcmaps = 0; c->desktop = 0; c->next = clients; clients = c; return c; } void rmclient (Client * c) { int i; Client *cc; if (prev_current == c) prev_current = 0; for (i = 0; i < num_screens; i++) { int d; for (d = 0; d < prefs.desktops; d++) { if (screens[i].focused[d] == c) screens[i].focused[d] = 0; if (screens[i].notilefocused[d] == c) screens[i].notilefocused[d] = 0; } } if (c == clients) { clients = c->next; } for (cc = clients; cc && cc->next; cc = cc->next) { if (cc->next == c) { cc->next = cc->next->next; } } if (hidden (c)) { unhidec (c, 0); } if (c->parent != c->screen->root) { XDestroyWindow (dpy, c->parent); } c->parent = c->window = None; if (current == c) { current = 0; revert_window (c->screen); } if (c->ncmapwins != 0) { XFree ((char *) c->cmapwins); free ((char *) c->wmcmaps); } if (c->iconname != 0) XFree ((char *) c->iconname); if (c->name != 0) XFree ((char *) c->name); if (c->instance != 0) XFree ((char *) c->instance); if (c->class != 0) XFree ((char *) c->class); memset (c, 0, sizeof (Client)); free (c); } larswm-7.5.3/dat.h0000644000000000000000000001530610075552111013714 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ /* Many changes by Lars Bernhardsson. */ /* Less changes by Florian Forster */ #define VERSION "larswm 7.5.3 [15-JUL-2004] by Lars Bernhardsson " #define BORDER 2 #define TILE_PAD 2 #define L_OFF_R 32768 #define L_OFF_G 32768 #define L_OFF_B 32768 #define L_ON_R 65535 #define L_ON_G 0 #define L_ON_B 0 #define L_DELTA 16384 #define L_TOP(x) (unsigned short) (((x) + L_DELTA) > 65535 ? 65535 : (x) + L_DELTA) #define L_BOT(x) (unsigned short) (((x) - L_DELTA) < 0 ? 0 : (x) - L_DELTA) #define BAR_HEIGHT (2 + font->ascent + font->descent) #define BAR_TEXT_Y (1 + font->ascent) #define BAR_X(s) 0 #define BAR_Y(s) (DisplayHeight (dpy, (s)->num) - BAR_HEIGHT) #define BAR_WIDTH(s) (DisplayWidth (dpy, (s)->num)) #define DEFSHELL "/bin/sh" #define DEFRC "/etc/X11/larswmrc" #define MAXSCREENS 4 #define MAXDESKTOPS 16 #define MAXFLOATCLASS 64 #define MAXTOOLCLASS 64 #define MAXSTICKYCLASS 64 #define MAXNOTILECLASS 64 #define MAXDTCLASS 64 #define MAXHIDDEN 64 #define MAXAPPS 64 #define MAXBTNAPPS 3 /* for zooming */ #define DIM_VERT 1 #define DIM_HORIZ 2 #define DIM_OUTSIDE 4 /* to keep track of if a window is zoomed max */ /* height/width/both or select zoomed */ #define ZOOM_UNZOOMED 0 #define ZOOM_NORMAL 1 #define ZOOM_SELECT 2 typedef struct Client Client; typedef struct ScreenInfo ScreenInfo; typedef struct Prefs Prefs; struct Client { Window window; Window parent; Window trans; Client *next; int x; int y; int dx; int dy; int border; int zx; int zy; int zdx; int zdy; int iszoom; int isleft; int isaside; int ax; int ay; XSizeHints size; int min_dx; int min_dy; int state; int hidden; int init; int reparenting; int proto; int desktop; int isfloat; int istool; int issticky; int isshaped; int isnotile; char *label; char *instance; char *class; char *name; char *iconname; Colormap cmap; int ncmapwins; Window *cmapwins; Colormap *wmcmaps; ScreenInfo *screen; }; #define hidden(c) ((c)->state == IconicState) #define withdrawn(c) ((c)->state == WithdrawnState) #define normal(c) ((c)->state == NormalState) /* c->proto */ #define Pdelete 1 #define Ptakefocus 2 struct ScreenInfo { int num; Window root; Window barwin; Colormap def_cmap; GC gc; #ifdef THREE_D GC topwhitegc; GC botwhitegc; GC topblackgc; GC botblackgc; #endif unsigned long black; unsigned long white; #ifdef THREE_D unsigned long topwhite; unsigned long botwhite; unsigned long topblack; unsigned long botblack; #endif int min_cmaps; Cursor place; Cursor sweep; char display[256]; int desktop; int tile_height; int res_height; int bigmr[MAXDESKTOPS]; int clickthru[MAXDESKTOPS]; int tile_resize[MAXDESKTOPS]; int skip_focus[MAXDESKTOPS]; int left_track_width[MAXDESKTOPS]; int notile_raised[MAXDESKTOPS]; Client *focused[MAXDESKTOPS]; Client *notilefocused[MAXDESKTOPS]; }; struct Prefs { int clickthru[MAXSCREENS][MAXDESKTOPS]; int tile_resize[MAXSCREENS][MAXDESKTOPS]; int skip_focus[MAXSCREENS][MAXDESKTOPS]; int left_track_width[MAXSCREENS][MAXDESKTOPS]; int desktops; char *dtname[MAXSCREENS][MAXDESKTOPS]; char *bgstr; char *fgstr; char *fname; char *application[MAXAPPS]; char *btnapplication[MAXBTNAPPS]; char *floatclass[MAXFLOATCLASS]; char *toolclass[MAXTOOLCLASS]; char *notileclass[MAXNOTILECLASS]; char *stickyclass[MAXSTICKYCLASS]; char *dtclass[MAXDTCLASS]; int dtnum[MAXDTCLASS]; /* keycodes for shortcuts */ KeySym prev_screen_key; unsigned long prev_screen_mod; KeySym next_screen_key; unsigned long next_screen_mod; KeySym prev_desktop_key; unsigned long prev_desktop_mod; KeySym next_desktop_key; unsigned long next_desktop_mod; KeySym prev_desktop_drag_key; unsigned long prev_desktop_drag_mod; KeySym next_desktop_drag_key; unsigned long next_desktop_drag_mod; KeySym prev_window_key; unsigned long prev_window_mod; KeySym next_window_key; unsigned long next_window_mod; KeySym raise_notile_key; unsigned long raise_notile_mod; KeySym move_northwest_key; unsigned long move_northwest_mod; KeySym move_north_key; unsigned long move_north_mod; KeySym move_northeast_key; unsigned long move_northeast_mod; KeySym move_west_key; unsigned long move_west_mod; KeySym move_center_key; unsigned long move_center_mod; KeySym move_east_key; unsigned long move_east_mod; KeySym move_southwest_key; unsigned long move_southwest_mod; KeySym move_south_key; unsigned long move_south_mod; KeySym move_southeast_key; unsigned long move_southeast_mod; KeySym move_select_key; unsigned long move_select_mod; KeySym move_aside_key; unsigned long move_aside_mod; KeySym move_aside_other_key; unsigned long move_aside_other_mod; KeySym move_sd_key; unsigned long move_sd_mod; KeySym toggle_inc_key; unsigned long toggle_inc_mod; KeySym move_up_key; unsigned long move_up_mod; KeySym move_down_key; unsigned long move_down_mod; KeySym move_left_key; unsigned long move_left_mod; KeySym move_right_key; unsigned long move_right_mod; KeySym grow_vert_key; unsigned long grow_vert_mod; KeySym shrink_vert_key; unsigned long shrink_vert_mod; KeySym grow_horiz_key; unsigned long grow_horiz_mod; KeySym shrink_horiz_key; unsigned long shrink_horiz_mod; KeySym grow_both_key; unsigned long grow_both_mod; KeySym shrink_both_key; unsigned long shrink_both_mod; KeySym zoom_vert_key; unsigned long zoom_vert_mod; KeySym zoom_horiz_key; unsigned long zoom_horiz_mod; KeySym zoom_full_key; unsigned long zoom_full_mod; KeySym zoom_full2_key; unsigned long zoom_full2_mod; KeySym hide_key; unsigned long hide_mod; KeySym unhide_key; unsigned long unhide_mod; KeySym close_key; unsigned long close_mod; KeySym goto_desktop_key[MAXDESKTOPS]; unsigned long goto_desktop_mod[MAXDESKTOPS]; KeySym application_key[MAXAPPS]; unsigned long application_mod[MAXAPPS]; }; /* main.c */ extern Display *dpy; extern ScreenInfo *screens; extern int num_screens; extern int initting; extern XFontStruct *font; extern char **myargv; extern Bool shape; extern char *shell; extern Atom exit_larswm; extern Atom restart_larswm; extern Atom bartext_larswm; extern Atom wm_state; extern Atom wm_change_state; extern Atom wm_protocols; extern Atom wm_delete; extern Atom wm_colormaps; /* client.c */ extern Client *clients; extern Client *current; extern Client *prev_current; /* buttons.c */ extern Client *hiddenc[]; extern int numhidden; /* error.c */ extern int ignore_badwindow; /* prefs.c */ extern Prefs prefs; /* bar.c */ extern int bar_hidden; larswm-7.5.3/error.c0000644000000000000000000000241010065667625014300 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" int ignore_badwindow; void fatal (char *s) { fprintf (stderr, "larswm: "); perror (s); fprintf (stderr, "\n"); exit (1); } int handler (Display * d, XErrorEvent * e) { char msg[80], req[80], number[80]; if (initting && (e->request_code == X_ChangeWindowAttributes) && (e->error_code == BadAccess)) { fprintf (stderr, "larswm: another wm already running?\n"); exit (1); } if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor)) return 0; XGetErrorText (d, e->error_code, msg, sizeof (msg)); sprintf (number, "%d", e->request_code); XGetErrorDatabaseText (d, "XRequest", number, "", req, sizeof (req)); if (req[0] == '\0') sprintf (req, "", e->request_code); fprintf (stderr, "larswm: %s(0x%x): %s\n", req, (unsigned int) e->resourceid, msg); if (initting) { fprintf (stderr, "larswm: failure during initialisation; aborting\n"); exit (1); } return 0; } larswm-7.5.3/event.c0000644000000000000000000002271410065667625014301 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" void mainloop (int shape_event) { Client *c = 0; ScreenInfo *s = 0; XEvent ev; for (;;) { XNextEvent (dpy, &ev); switch (ev.type) { case KeyPress: keyevent (&ev.xkey); break; case KeyRelease: break; case ButtonPress: button (&ev.xbutton); XAllowEvents (dpy, SyncPointer, ev.xbutton.time); break; case ButtonRelease: break; case MapRequest: mapreq (&ev.xmaprequest); if ((c = getclient (ev.xmaprequest.window, 0)) != 0) { if (normal (c) && ((s = c->screen) != 0)) { if (c == current) { if (c->isnotile) { raise_notile (s); } else { raise_tile (s, 0); } } if (!c->isnotile || c->istool) { tile_all (s); } } } break; case ConfigureRequest: configurereq (&ev.xconfigurerequest); break; case UnmapNotify: unmap (&ev.xunmap); if ((c = getclient (ev.xunmap.window, 0)) != 0) { if ((s = c->screen) != 0) { if (!c->isnotile || c->istool) { tile_all (s); } if (!current) { revert_window (s); } } } break; case PropertyNotify: property (&ev.xproperty); break; case Expose: expose (&ev.xexpose); break; case CreateNotify: newwindow (&ev.xcreatewindow); break; case DestroyNotify: destroy (ev.xdestroywindow.window); break; case ClientMessage: clientmesg (&ev.xclient); break; case ColormapNotify: cmap (&ev.xcolormap); break; case ReparentNotify: reparent (&ev.xreparent); break; case SelectionNotify: break; case EnterNotify: enter (&ev.xcrossing); break; case FocusIn: focusin (&ev.xfocus); break; default: if (shape && ev.type == shape_event) { shapenotify ((XShapeEvent *) & ev); } break; } } } void expose (XExposeEvent * e) { Client *c; ScreenInfo *s; if ((c = getclient (e->window, 0))) draw_border (c, c == current ? 1 : 0); else if ((s = getbarscreen (e->window))) draw_tbar (s); } void configurereq (XConfigureRequestEvent * e) { XWindowChanges wc; Client *c; c = getclient (e->window, 0); e->value_mask &= ~CWSibling; if (c) { gravitate (c, 1); if (e->value_mask & CWX) c->x = e->x; if (e->value_mask & CWY) c->y = e->y; if (e->value_mask & CWWidth) c->dx = e->width; if (e->value_mask & CWHeight) c->dy = e->height; if (e->value_mask & CWBorderWidth) c->border = e->border_width; gravitate (c, 0); if (e->value_mask & CWStackMode) { if (wc.stack_mode == Above) top (c); else e->value_mask &= ~CWStackMode; } if (c->parent != c->screen->root && c->window == e->window) { wc.x = c->x - BORDER; wc.y = c->y - BORDER; wc.width = c->dx + 2 * BORDER; wc.height = c->dy + 2 * BORDER; wc.border_width = 1; wc.sibling = None; wc.stack_mode = e->detail; XConfigureWindow (dpy, c->parent, e->value_mask, &wc); sendconfig (c); } } if (c && c->init) { wc.x = BORDER; wc.y = BORDER; } else { wc.x = e->x; wc.y = e->y; } wc.width = e->width; wc.height = e->height; wc.border_width = 0; wc.sibling = None; wc.stack_mode = Above; e->value_mask &= ~CWStackMode; e->value_mask |= CWBorderWidth; XConfigureWindow (dpy, e->window, e->value_mask, &wc); } void mapreq (XMapRequestEvent * e) { Client *c; c = getclient (e->window, 0); if (c == 0 || c->window != e->window) { return; } switch (c->state) { case WithdrawnState: if (c->parent == c->screen->root) { if (!manage (c, 0)) return; break; } XReparentWindow (dpy, c->window, c->parent, BORDER, BORDER); XAddToSaveSet (dpy, c->window); /* fall through... */ case NormalState: if (c->trans != None) { Client *p = getclient (c->trans, 0); if (p) { c->desktop = p->desktop; } } raise_tbar (c->screen); XMapWindow (dpy, c->window); XMapRaised (dpy, c->parent); top (c); wmsetstate (c, NormalState); if ((mouse_on_screen () == c->screen) || (current && (current->screen == c->screen))) { active (c); } break; case IconicState: unhidec (c, 1); break; } } void unmap (XUnmapEvent * e) { Client *c; c = getclient (e->window, 0); if (c) { switch (c->state) { case IconicState: if (e->send_event) { unhidec (c, 0); withdraw (c); } break; case NormalState: if (c == current) current = 0; if (!c->reparenting) withdraw (c); break; } c->reparenting = 0; } } void newwindow (XCreateWindowEvent * e) { Client *c; ScreenInfo *s; if (e->override_redirect) return; c = getclient (e->window, 1); /* Crashing bug patch by MG has been applied here. */ if (c && c->window == e->window) { c->x = e->x; c->y = e->y; c->dx = e->width; c->dy = e->height; c->border = e->border_width; if (0 != (s = getscreen (e->parent))) c->screen = s; else c->screen = &screens[0]; if (c->parent == None) c->parent = c->screen->root; } } void destroy (Window w) { Client *c; if (!(c = getclient (w, 0))) return; rmclient (c); ignore_badwindow = 1; XSync (dpy, False); ignore_badwindow = 0; } void clientmesg (XClientMessageEvent * e) { Client *c; if (e->message_type == exit_larswm) { cleanup (); exit (0); } else if (e->message_type == restart_larswm) { cleanup (); execvp (myargv[0], myargv); perror ("larswm: exec failed"); exit (1); } else if (e->message_type == wm_change_state) { c = getclient (e->window, 0); if (e->format == 32 && e->data.l[0] == IconicState && c != 0) { if (normal (c)) hide (c); } } } void cmap (XColormapEvent * e) { Client *c; int i; if (e->new) { c = getclient (e->window, 0); if (c) { c->cmap = e->colormap; if (c == current) cmapfocus (c); } else for (c = clients; c; c = c->next) { for (i = 0; i < c->ncmapwins; i++) if (c->cmapwins[i] == e->window) { c->wmcmaps[i] = e->colormap; if (c == current) cmapfocus (c); return; } } } } void property (XPropertyEvent * e) { Client *c; long msize; /* check if text to be displayed on status bar was just changed */ if ((e->atom == bartext_larswm) && (e->window == DefaultRootWindow (dpy))) { update_cmd_output (); return; } if (!(c = getclient (e->window, 0))) return; switch (e->atom) { case XA_WM_ICON_NAME: if (c->iconname != 0) XFree ((char *) c->iconname); c->iconname = (e->state == PropertyDelete) ? 0 : getprop (c->window, e->atom); setlabel (c); renamec (c, c->label); break; case XA_WM_NAME: if (c->name != 0) XFree ((char *) c->name); c->name = (e->state == PropertyDelete) ? 0 : getprop (c->window, e->atom); setlabel (c); renamec (c, c->label); break; case XA_WM_TRANSIENT_FOR: gettrans (c); break; case XA_WM_NORMAL_HINTS: if (XGetWMNormalHints (dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0) { c->size.flags = PSize; } if (c->size.flags & PBaseSize) { c->min_dx = c->size.base_width; c->min_dy = c->size.base_height; } else if (c->size.flags & PMinSize) { c->min_dx = c->size.min_width; c->min_dy = c->size.min_height; } else { c->min_dx = c->min_dy = 1; } break; default: if (e->atom == wm_colormaps) { getcmaps (c); if (c == current) { cmapfocus (c); } } break; } } void reparent (XReparentEvent * e) { Client *c; XWindowAttributes attr; ScreenInfo *s; if (!getscreen (e->event) || e->override_redirect) return; if ((s = getscreen (e->parent)) != 0) { c = getclient (e->window, 1); if (c != 0 && (c->dx == 0 || c->dy == 0)) { XGetWindowAttributes (dpy, c->window, &attr); c->x = attr.x; c->y = attr.y; c->dx = attr.width; c->dy = attr.height; c->border = attr.border_width; c->screen = s; if (c->parent == None) c->parent = c->screen->root; } } else { c = getclient (e->window, 0); if (c != 0 && (c->parent == c->screen->root || withdrawn (c))) rmclient (c); } } void shapenotify (XShapeEvent * e) { Client *c; c = getclient (e->window, 0); if (c == 0) return; setshape (c); } void enter (XCrossingEvent * e) { Client *c; if (e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual) return; c = getclient (e->window, 0); if (c && c->parent && (c != current)) { XMapRaised (dpy, c->parent); active (c); } else { XSetInputFocus (dpy, e->window, RevertToPointerRoot, e->time); } } void focusin (XFocusChangeEvent * e) { Client *c; if (e->detail != NotifyNonlinearVirtual) return; c = getclient (e->window, 0); if (c && c->window && c->parent && (c->window == e->window) && (c != current)) { XMapRaised (dpy, c->parent); active (c); } else { XSetInputFocus (dpy, e->window, RevertToPointerRoot, CurrentTime); } } larswm-7.5.3/fns.h0000644000000000000000000001047210065667625013751 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ /* main.c */ void usage (void); void initscreen (ScreenInfo *, int); ScreenInfo *getscreen (Window); void sendcmessage (Window, Atom, long, int); void sendconfig (Client *); void cleanup (void); /* event.c */ void mainloop (int); void selection (XSelectionEvent *); void expose (XExposeEvent *); void configurereq (XConfigureRequestEvent *); void mapreq (XMapRequestEvent *); void unmap (XUnmapEvent *); void newwindow (XCreateWindowEvent *); void destroy (Window); void clientmesg (XClientMessageEvent *); void cmap (XColormapEvent *); void property (XPropertyEvent *); void shapenotify (XShapeEvent *); void reparent (XReparentEvent *); void enter (XCrossingEvent *); void focusin (XFocusChangeEvent *); /* manage.c */ int manage (Client *, int); void scanwins (ScreenInfo *); void setshape (Client *); void withdraw (Client *); void gravitate (Client *, int); void cmapfocus (Client *); void cmapnofocus (ScreenInfo *); void getcmaps (Client *); int _getprop (Window, Atom, Atom, long, unsigned char **); char *getprop (Window, Atom); int getstate (Window, int *); void wmsetstate (Client *, int); void setlabel (Client *); void getproto (Client *); void gettrans (Client *); /* mouse.c */ void move_opaque (Client *); void resize_opaque (Client *); /* buttons.c */ void button (XButtonEvent *); void spawn (ScreenInfo *, char *); void wmdelete (Client *, int); void hide (Client *); void unhide (int, int); void unhidec (Client *, int); void renamec (Client *, char *); /* client.c */ void setactive (Client *, int); void draw_border (Client *, int); void active (Client *); void nofocus (void); void top (Client *); Client *getclient (Window, int); void rmclient (Client *); /* error.c */ int handler (Display *, XErrorEvent *); void fatal (char *); /* tiling.c */ void getmouse (int *, int *, ScreenInfo *); void setmouse (int, int, ScreenInfo *); int is_float (Client *); int is_notile (Client *); int is_tool (Client *); int is_sticky (Client *); int is_dt (Client *); void toggle_inc (ScreenInfo *); void toggle_notile (ScreenInfo *); void raise_tile (ScreenInfo *, int); void raise_notile (ScreenInfo *); void toggle_isfloat (Client *); void toggle_istool (Client *); void toggle_issticky (Client *); void toggle_clickthru (ScreenInfo *); void toggle_tile_resize (ScreenInfo *); int count_clients (ScreenInfo *); void calc_track_sizes (ScreenInfo *); void tile_all (ScreenInfo *); void move_hide (Client *); void move_show (Client *); void update_desktop (ScreenInfo *); void next_desktop (ScreenInfo *); void next_desktop_drag (ScreenInfo *); void prev_desktop (ScreenInfo *); void prev_desktop_drag (ScreenInfo *); void goto_desktop (ScreenInfo *, int); void toggle_skip_focus (ScreenInfo *); void revert_window (ScreenInfo *); void revert_same (ScreenInfo *); void prev_window (ScreenInfo *); void next_window (ScreenInfo *); void prev_screen (ScreenInfo *); void next_screen (ScreenInfo *); void shrink_left (ScreenInfo *); void grow_left (ScreenInfo *); void max_left (ScreenInfo *); void restore_left (ScreenInfo *); ScreenInfo *mouse_on_screen (void); void move_northwest (Client *); void move_north (Client *); void move_northeast (Client *); void move_west (Client *); void move_center (Client *); void move_east (Client *); void move_southwest (Client *); void move_south (Client *); void move_southeast (Client *); void move_up (Client *); void move_down (Client *); void move_left (Client *); void move_right (Client *); void move_select (Client *, int); int count_aside (ScreenInfo *); Client *find_aside (ScreenInfo *); void arrange_aside (ScreenInfo *); void move_aside (ScreenInfo *, Client *); void move_aside_other (ScreenInfo *); void move_aside_clear (ScreenInfo *, Client *); void zoom (Client *, int); void grow (Client *, int, int); void move_sd (Client *); /* prefs.c */ void set_defaults (void); void dump_prefs (void); void validate_prefs (void); void load_prefs (char *); /* keys.c */ void initkeys (Client *); void keyevent (XKeyEvent *); /* bar.c */ void do_menu (ScreenInfo *); void prev_menu (void); void next_menu (void); void show_hidden (void); void prev_hidden (void); void next_hidden (void); void toggle_show_class (void); void update_cmd_output (void); void draw_tbar (ScreenInfo *); void update_tbar (void); void raise_tbar (ScreenInfo *); ScreenInfo *getbarscreen (Window); larswm-7.5.3/Imakefile0000644000000000000000000000117010070137332014575 0ustar rootroot00000000000000CCOPTIONS=-DTHREE_D -DUSE_LOCALE PROGRAMS = larswm larsremote larsclock larsmenu SRCS1 = main.c event.c manage.c buttons.c client.c error.c tiling.c prefs.c keys.c mouse.c bar.c OBJS1 = main.o event.o manage.o buttons.o client.o error.o tiling.o prefs.o keys.o mouse.o bar.o SRCS2 = larsremote.c OBJS2 = larsremote.o SRCS3 = larsclock.c OBJS3 = larsclock.o SRCS4 = larsmenu.c OBJS4 = larsmenu.o ComplexProgramTarget_1(larswm, $(XLIB), NullParameter) ComplexProgramTarget_2(larsremote, $(XLIB), NullParameter) ComplexProgramTarget_3(larsclock, $(XLIB), NullParameter) ComplexProgramTarget_4(larsmenu, $(XMULIB), NullParameter) larswm-7.5.3/keys.c0000644000000000000000000003516310065667625014135 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" void unhide_last (ScreenInfo * s) { int i; for (i = numhidden - 1; i >= 0; i--) { Client *c = hiddenc[i]; if (c->screen == s) { unhidec (c, 1); if (!c->isnotile) tile_all (s); return; } } } void initkeys (Client * c) { if (c) { int y; /* only do this if there's a window to grab keys from */ if (prefs.prev_window_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_window_key), prefs.prev_window_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.next_window_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_window_key), prefs.next_window_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_northwest_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_northwest_key), prefs.move_northwest_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_north_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_north_key), prefs.move_north_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_northeast_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_northeast_key), prefs.move_northeast_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_west_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_west_key), prefs.move_west_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_center_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_center_key), prefs.move_center_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_east_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_east_key), prefs.move_east_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_southwest_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_southwest_key), prefs.move_southwest_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_south_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_south_key), prefs.move_south_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_southeast_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_southeast_key), prefs.move_southeast_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_up_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_up_key), prefs.move_up_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_down_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_down_key), prefs.move_down_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_left_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_left_key), prefs.move_left_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_right_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_right_key), prefs.move_right_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_select_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_select_key), prefs.move_select_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_aside_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_aside_key), prefs.move_aside_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_aside_other_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_aside_other_key), prefs.move_aside_other_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.move_sd_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_sd_key), prefs.move_sd_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.grow_vert_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.grow_vert_key), prefs.grow_vert_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.shrink_vert_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.shrink_vert_key), prefs.shrink_vert_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.grow_horiz_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.grow_horiz_key), prefs.grow_horiz_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.shrink_horiz_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.shrink_horiz_key), prefs.shrink_horiz_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.grow_both_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.grow_both_key), prefs.grow_both_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.shrink_both_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.shrink_both_key), prefs.shrink_both_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.zoom_vert_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.zoom_vert_key), prefs.zoom_vert_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.zoom_horiz_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.zoom_horiz_key), prefs.zoom_horiz_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.zoom_full_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.zoom_full_key), prefs.zoom_full_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.zoom_full2_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.zoom_full2_key), prefs.zoom_full2_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.hide_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.hide_key), prefs.hide_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.close_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.close_key), prefs.close_mod, c->parent, True, GrabModeAsync, GrabModeAsync); /* same as root window grab */ if (num_screens > 1) { if (prefs.prev_screen_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_screen_key), prefs.prev_screen_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.next_screen_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_screen_key), prefs.next_screen_mod, c->parent, True, GrabModeAsync, GrabModeAsync); } if (prefs.prev_desktop_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_desktop_key), prefs.prev_desktop_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.prev_desktop_drag_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_desktop_drag_key), prefs.prev_desktop_drag_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.next_desktop_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_desktop_key), prefs.next_desktop_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.next_desktop_drag_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_desktop_drag_key), prefs.next_desktop_drag_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.toggle_inc_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.toggle_inc_key), prefs.toggle_inc_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.raise_notile_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.raise_notile_key), prefs.raise_notile_mod, c->parent, True, GrabModeAsync, GrabModeAsync); if (prefs.unhide_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.unhide_key), prefs.unhide_mod, c->parent, True, GrabModeAsync, GrabModeAsync); for (y = 0; y < prefs.desktops; y++) if (prefs.goto_desktop_key[y]) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.goto_desktop_key[y]), prefs.goto_desktop_mod[y], c->parent, True, GrabModeAsync, GrabModeAsync); for (y = 0; y < MAXAPPS; y++) if (prefs.application[y] && prefs.application_key[y]) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.application_key[y]), prefs.application_mod[y], c->parent, True, GrabModeAsync, GrabModeAsync); } else { int i; XUngrabKeyboard (dpy, CurrentTime); for (i = 0; i < num_screens; i++) { int y; if (num_screens > 1) { if (prefs.prev_screen_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_screen_key), prefs.prev_screen_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.next_screen_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_screen_key), prefs.next_screen_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); } if (prefs.prev_desktop_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.prev_desktop_key), prefs.prev_desktop_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.next_desktop_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.next_desktop_key), prefs.next_desktop_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.toggle_inc_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.toggle_inc_key), prefs.toggle_inc_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.raise_notile_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.raise_notile_key), prefs.raise_notile_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.unhide_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.unhide_key), prefs.unhide_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); if (prefs.move_aside_key) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.move_aside_key), prefs.move_aside_mod, screens[i].root, True, GrabModeAsync, GrabModeAsync); for (y = 0; y < prefs.desktops; y++) if (prefs.goto_desktop_key[y]) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.goto_desktop_key[y]), prefs.goto_desktop_mod[y], screens[i].root, True, GrabModeAsync, GrabModeAsync); for (y = 0; y < MAXAPPS; y++) if (prefs.application[y] && prefs.application_key[y]) XGrabKey (dpy, XKeysymToKeycode (dpy, prefs.application_key[y]), prefs.application_mod[y], screens[i].root, True, GrabModeAsync, GrabModeAsync); } } } void keyevent (XKeyEvent * e) { Client *c; ScreenInfo *s; KeySym k; unsigned long m; if ((s = getscreen (e->root)) == 0) return; c = getclient (e->window, 0); k = XKeycodeToKeysym (dpy, e->keycode, 0); m = e->state; if (k == prefs.prev_screen_key && m == prefs.prev_screen_mod) prev_screen (s); else if (k == prefs.next_screen_key && m == prefs.next_screen_mod) next_screen (s); else if (k == prefs.prev_desktop_key && m == prefs.prev_desktop_mod) prev_desktop (s); else if (k == prefs.prev_desktop_drag_key && m == prefs.prev_desktop_drag_mod) prev_desktop_drag (s); else if (k == prefs.next_desktop_key && m == prefs.next_desktop_mod) next_desktop (s); else if (k == prefs.next_desktop_drag_key && m == prefs.next_desktop_drag_mod) next_desktop_drag (s); else if (k == prefs.prev_window_key && m == prefs.prev_window_mod) prev_window (s); else if (k == prefs.next_window_key && m == prefs.next_window_mod) next_window (s); else if (k == prefs.raise_notile_key && m == prefs.raise_notile_mod) toggle_notile (s); else if (k == prefs.move_northwest_key && m == prefs.move_northwest_mod) move_northwest (current); else if (k == prefs.move_north_key && m == prefs.move_north_mod) move_north (current); else if (k == prefs.move_northeast_key && m == prefs.move_northeast_mod) move_northeast (current); else if (k == prefs.move_west_key && m == prefs.move_west_mod) move_west (current); else if (k == prefs.move_center_key && m == prefs.move_center_mod) move_center (current); else if (k == prefs.move_east_key && m == prefs.move_east_mod) move_east (current); else if (k == prefs.move_southwest_key && m == prefs.move_southwest_mod) move_southwest (current); else if (k == prefs.move_south_key && m == prefs.move_south_mod) move_south (current); else if (k == prefs.move_southeast_key && m == prefs.move_southeast_mod) move_southeast (current); else if (k == prefs.toggle_inc_key && m == prefs.toggle_inc_mod) toggle_inc (s); else if (k == prefs.move_up_key && m == prefs.move_up_mod) move_up (current); else if (k == prefs.move_down_key && m == prefs.move_down_mod) move_down (current); else if (k == prefs.move_left_key && m == prefs.move_left_mod) move_left (current); else if (k == prefs.move_right_key && m == prefs.move_right_mod) move_right (current); else if (k == prefs.move_select_key && m == prefs.move_select_mod) move_select (current, 0); else if (k == prefs.move_aside_key && m == prefs.move_aside_mod) move_aside (s, current); else if (k == prefs.move_aside_other_key && m == prefs.move_aside_other_mod) move_aside_other (s); else if (k == prefs.move_sd_key && m == prefs.move_sd_mod) move_sd (current); else if (k == prefs.grow_vert_key && m == prefs.grow_vert_mod) grow (current, DIM_VERT, 1); else if (k == prefs.shrink_vert_key && m == prefs.shrink_vert_mod) grow (current, DIM_VERT, -1); else if (k == prefs.grow_horiz_key && m == prefs.grow_horiz_mod) grow (current, DIM_HORIZ, 1); else if (k == prefs.shrink_horiz_key && m == prefs.shrink_horiz_mod) grow (current, DIM_HORIZ, -1); else if (k == prefs.grow_both_key && m == prefs.grow_both_mod) grow (current, DIM_VERT | DIM_HORIZ, 1); else if (k == prefs.shrink_both_key && m == prefs.shrink_both_mod) grow (current, DIM_VERT | DIM_HORIZ, -1); else if (k == prefs.zoom_vert_key && m == prefs.zoom_vert_mod) zoom (current, DIM_VERT); else if (k == prefs.zoom_horiz_key && m == prefs.zoom_horiz_mod) zoom (current, DIM_HORIZ); else if (k == prefs.zoom_full_key && m == prefs.zoom_full_mod) zoom (current, (DIM_VERT | DIM_HORIZ)); else if (k == prefs.zoom_full2_key && m == prefs.zoom_full2_mod) zoom (current, (DIM_VERT | DIM_HORIZ | DIM_OUTSIDE)); else if (k == prefs.hide_key && m == prefs.hide_mod) hide (current); else if (k == prefs.unhide_key && m == prefs.unhide_mod) unhide_last (s); else if (k == prefs.close_key && m == prefs.close_mod) wmdelete (current, 0); else { int i; for (i = 0; i < prefs.desktops; i++) { if (k == prefs.goto_desktop_key[i] && m == prefs.goto_desktop_mod[i]) { goto_desktop (s, i); return; } } for (i = 0; i < MAXAPPS; i++) { if (prefs.application[i] && (k == prefs.application_key[i]) && (m == prefs.application_mod[i])) { spawn (s, prefs.application[i]); return; } } XAllowEvents (dpy, ReplayKeyboard, e->time); } } larswm-7.5.3/larsclock.c0000644000000000000000000000305110070137412015104 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ /* * Minimal clock app for larswm. No fork()/exec() is done, it updates * the status bar by setting the LARSWM_BARTEXT atom every second. */ #include #include #include #include #ifdef USE_LOCALE #include #endif #include #include #include #include #include #define CLOCK_LENGTH 100 int main (int argc, char **argv) { int i; time_t t; char *slist; char *format = "%c"; char *display_string = ""; Display *dpy; Atom bartext_larswm; XTextProperty pr; #ifdef USE_LOCALE setlocale (LC_ALL, ""); #endif for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-display") == 0 && i + 1 < argc) { display_string = argv[++i]; } else if (strcmp (argv[i], "-format") == 0 && i + 1 < argc) { format = argv[++i]; } else { fprintf (stderr, "usage: %s [-display display] [-format format]\n", argv[0]); exit (1); } } dpy = XOpenDisplay (display_string); if (dpy == 0) { perror ("XOpenDisplay"); exit (1); } bartext_larswm = XInternAtom (dpy, "LARSWM_BARTEXT", False); slist = malloc (CLOCK_LENGTH); while (1) { time (&t); strftime (slist, CLOCK_LENGTH, format, localtime (&t)); XStringListToTextProperty (&slist, 1, &pr); XSetTextProperty (dpy, DefaultRootWindow (dpy), &pr, bartext_larswm); XFree (pr.value); XSync (dpy, False); sleep (1); } } larswm-7.5.3/larsclock.man0000644000000000000000000000123010065667625015454 0ustar rootroot00000000000000.TH larsclock 1x .SH NAME larsclock \- Status bar clock for larswm .SH SYNOPSIS .B larsclock [ .B \-display .I dpy ] [ .B \-format .I fmt ] .SH DESCRIPTION .I larsclock is a minimal status bar clock application for the larswm window manager. .SH OPTIONS The following command line options are supported: .TP 18 .BI \-display " dpy" lets you specify which display you want .I larsclock to open. .TP 18 .BI \-format " fmt" lets you format how the time is displayed. The default format is "%c". See strftime(3) for details. .SH SEE ALSO larsmenu(1x), larsremote(1x), larswm(1x), strftime(3x) .SH AUTHORS .I larsclock was created by Lars Bernhardsson . larswm-7.5.3/larsmenu.c0000644000000000000000000005166610070132031014764 0ustar rootroot00000000000000/* * 9menu.c * * This program puts up a window that is just a menu, and executes * commands that correspond to the items selected. * * Initial idea: Arnold Robbins * Version using libXg: Matty Farrow (some ideas borrowed) * This code by: David Hogan and Arnold Robbins * * Copyright (c), Arnold Robbins and David Hogan * * Arnold Robbins * arnold@skeeve.com * October, 1994 * * Code added to cause pop-up (unIconify) to move menu to mouse. * Christopher Platt * platt@coos.dartmouth.edu * May, 1995 * * Said code moved to -teleport option, and -warp option added. * Arnold Robbins * June, 1995 * * Code added to allow -fg and -bg colors. * John M. O'Donnell * odonnell@stpaul.lampf.lanl.gov * April, 1997 * * Code added for -file and -path optioins. * Peter Seebach * seebs@plethora.net * October, 2001 * * Code added to allow up and down arrow keys to go up * and down menu and RETURN to select an item. * Matthias Bauer * bauerm@immd1.informatik.uni-erlangen.de * June 2003 * * Changed a couple of minor details, renamed it to larsmenu * so as to not cause conflicts when using package managers * to install both larswm and 9menu, and changed function * prototypes to ANSI C model. Added code to prevent it from * being started more than once. * Lars Bernhardsson * lab@fnurt.net * May 2004. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Display *dpy; /* lovely X stuff */ int screen; Window root; Window menuwin; GC gc; unsigned long black; unsigned long white; char *fgcname = NULL; char *bgcname = NULL; Colormap defcmap; XColor color; XFontStruct *font; Atom wm_protocols; Atom wm_delete_window; int g_argc; /* for XSetWMProperties to use */ char **g_argv; int f_argc; /* for labels read from files */ char **f_argv; char *geometry = ""; int savex, savey; Window savewindow; char *fontlist[] = { /* default font list if no -font */ "fixed", NULL }; /* the 9menu icon, for garish window managers */ #define nine_menu_width 40 #define nine_menu_height 40 static unsigned char nine_menu_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0xe0, 0x01, 0x04, 0x00, 0x80, 0xe0, 0x00, 0xfc, 0xff, 0xff, 0xe0, 0x01, 0xfc, 0xff, 0xff, 0x20, 0x03, 0x04, 0x00, 0x80, 0x00, 0x06, 0x04, 0x00, 0x80, 0x00, 0x0c, 0xfc, 0xff, 0xff, 0x00, 0x08, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Modify this to your liking */ #define CONFIG_MENU_UP_KEY XK_Up #define CONFIG_MENU_DOWN_KEY XK_Down #define CONFIG_MENU_SELECT_KEY XK_Return #define CONFIG_MENU_CANCEL_KEY XK_Escape #define PADX 100 #define PADY 30 char *progname; /* my name */ char *displayname; /* X display */ char *fontname; /* font */ char *labelname; /* window and icon name */ char *filename; /* file to read options or labels from */ int popup; /* true if we're a popup window */ int popdown; /* autohide after running a command */ int iconic; /* start iconified */ int teleport; /* teleport the menu */ int warp; /* warp the mouse */ char **labels; /* list of labels and commands */ char **commands; int numitems; char *shell = "/bin/sh"; /* default shell */ extern void usage (), run_menu (), spawn (), ask_wm_for_delete (); extern void reap (), set_wm_hints (); extern void redraw (), teleportmenu (), warpmouse (), restoremouse (); extern void memory (); extern int args (); /* scanwins --- check if a larsmenu window is already open. * Yes, this way is ugly. I know. Really, I know. =) */ int larsmenu_open (void) { unsigned int i, nwins, do_exit = 0; Window dw1, dw2, *wins; XQueryTree (dpy, root, &dw1, &dw2, &wins, &nwins); for (i = 0; i < nwins; i++) { Window client; XClassHint clh; if ((client = XmuClientWindow (dpy, wins[i])) != None) { if (XGetClassHint (dpy, client, &clh)) { if (clh.res_class && clh.res_name) { if (!strcmp (clh.res_class, "larsmenu") && !strcmp (clh.res_name, "larsmenu")) do_exit = 1; } if (clh.res_class) XFree (clh.res_class); if (clh.res_name) XFree (clh.res_name); } } if (do_exit) break; } XFree ((void *) wins); return do_exit; } /* memory --- print the out of memory message and die */ void memory (char *s) { fprintf (stderr, "%s: couldn't allocate memory for %s\n", progname, s); exit (1); } /* args --- go through the argument list, set options */ int args (int argc, char **argv) { int i; if (argc == 0 || argv == NULL || argv[0] == '\0') return -1; for (i = 0; i < argc && argv[i] != NULL; i++) { if (strcmp (argv[i], "-display") == 0) { displayname = argv[i + 1]; i++; } else if (strcmp (argv[i], "-file") == 0) { filename = argv[i + 1]; i++; } else if (strcmp (argv[i], "-font") == 0) { fontname = argv[i + 1]; i++; } else if (strcmp (argv[i], "-geometry") == 0) { geometry = argv[i + 1]; i++; } else if (strcmp (argv[i], "-label") == 0) { labelname = argv[i + 1]; i++; } else if (strcmp (argv[i], "-shell") == 0) { shell = argv[i + 1]; i++; } else if (strcmp (argv[i], "-popup") == 0) popup++; else if (strcmp (argv[i], "-popdown") == 0) popdown++; else if (strcmp (argv[i], "-fg") == 0) fgcname = argv[++i]; else if (strcmp (argv[i], "-bg") == 0) bgcname = argv[++i]; else if (strcmp (argv[i], "-iconic") == 0) iconic++; else if (strcmp (argv[i], "-path") == 0) { char pathbuf[MAXPATHLEN]; char *s, *t; s = getenv ("PATH"); if (s != NULL) { /* append current dir to PATH */ getcwd (pathbuf, MAXPATHLEN); t = malloc (strlen (s) + strlen (pathbuf) + 7); sprintf (t, "PATH=%s:%s", pathbuf, s); putenv (t); } } else if (strcmp (argv[i], "-teleport") == 0) teleport++; else if (strcmp (argv[i], "-warp") == 0) warp++; else if (argv[i][0] == '-') usage (); else break; } return i; } /* main --- crack arguments, set up X stuff, run the main menu loop */ int main (int argc, char **argv) { int i, j; char *cp; XGCValues gv; unsigned long mask; int nlabels = 0; g_argc = argc; g_argv = argv; /* set default label name */ if ((cp = strrchr (argv[0], '/')) == NULL) labelname = argv[0]; else labelname = ++cp; ++argv; --argc; /* and program name for diagnostics */ progname = labelname; i = args (argc, argv); numitems = argc - i; if (numitems <= 0 && filename == NULL) usage (); if (filename) { /* Read options and labels from file */ char fbuf[1024]; FILE *fp; fp = fopen (filename, "r"); if (fp == NULL) { fprintf (stderr, "%s: couldn't open '%s'\n", progname, filename); exit (1); } while (fgets (fbuf, sizeof fbuf, fp)) { char *s = fbuf; strtok (s, "\n"); if (s[0] == '-') { char *temp[3]; temp[0] = s; temp[1] = strchr (s, ' '); if (temp[1]) { *(temp[1]++) = '\0'; s = malloc (strlen (temp[1]) + 1); if (s == NULL) memory ("temporary argument"); strcpy (s, temp[1]); temp[1] = s; } temp[2] = 0; args (temp[1] ? 2 : 1, temp); continue; } if (s[0] == '#') continue; /* allow - in menu items to be escaped */ if (s[0] == '\\') ++s; /* allocate space */ if (f_argc < nlabels + 1) { int k; char **temp = malloc (sizeof (char *) * (f_argc + 5)); if (temp == 0) memory ("temporary item"); for (k = 0; k < nlabels; k++) temp[k] = f_argv[k]; free (f_argv); f_argv = temp; f_argc += 5; } f_argv[nlabels] = malloc (strlen (s) + 1); if (f_argv[nlabels] == NULL) memory ("temporary text"); strcpy (f_argv[nlabels], s); ++nlabels; } } labels = (char **) malloc ((numitems + nlabels) * sizeof (char *)); commands = (char **) malloc ((numitems + nlabels) * sizeof (char *)); if (commands == NULL || labels == NULL) memory ("command and label arrays"); for (j = 0; j < numitems; j++) { labels[j] = argv[i + j]; if ((cp = strchr (labels[j], ':')) != NULL) { *cp++ = '\0'; commands[j] = cp; } else commands[j] = labels[j]; } /* * Now we no longer need i (our offset into argv) so we recycle it, * while keeping the old value of j! */ for (i = 0; i < nlabels; i++) { labels[j] = f_argv[i]; if ((cp = strchr (labels[j], ':')) != NULL) { *cp++ = '\0'; commands[j] = cp; } else commands[j] = labels[j]; ++j; } /* And now we merge the totals */ numitems += nlabels; dpy = XOpenDisplay (displayname); if (dpy == NULL) { fprintf (stderr, "%s: cannot open display", progname); if (displayname != NULL) fprintf (stderr, " %s", displayname); fprintf (stderr, "\n"); exit (1); } screen = DefaultScreen (dpy); root = RootWindow (dpy, screen); /* * This used to be * black = BlackPixel(dpy, screen); * white = WhitePixel(dpy, screen); */ defcmap = DefaultColormap (dpy, screen); if (fgcname == NULL || XParseColor (dpy, defcmap, fgcname, &color) == 0 || XAllocColor (dpy, defcmap, &color) == 0) black = BlackPixel (dpy, screen); else black = color.pixel; if (bgcname == NULL || XParseColor (dpy, defcmap, bgcname, &color) == 0 || XAllocColor (dpy, defcmap, &color) == 0) white = WhitePixel (dpy, screen); else white = color.pixel; /* try user's font first */ if (fontname != NULL) { font = XLoadQueryFont (dpy, fontname); if (font == NULL) fprintf (stderr, "%s: warning: can't load font %s\n", progname, fontname); } /* if no user font, try one of our default fonts */ if (font == NULL) { for (i = 0; fontlist[i] != NULL; i++) { font = XLoadQueryFont (dpy, fontlist[i]); if (font != NULL) break; } } if (font == NULL) { fprintf (stderr, "%s: fatal: cannot load a font\n", progname); exit (1); } gv.foreground = black ^ white; gv.background = white; gv.font = font->fid; gv.function = GXxor; gv.line_width = 0; mask = GCForeground | GCBackground | GCFunction | GCFont | GCLineWidth; gc = XCreateGC (dpy, root, mask, &gv); signal (SIGCHLD, reap); if (!larsmenu_open ()) run_menu (); XCloseDisplay (dpy); exit (0); } /* spawn --- run a command */ void spawn (char *com) { int pid; static char *sh_base = NULL; if (sh_base == NULL) { sh_base = strrchr (shell, '/'); if (sh_base != NULL) sh_base++; else sh_base = shell; } if (strncmp (com, "exec ", 5) != 0) { pid = fork (); if (pid < 0) { fprintf (stderr, "%s: can't fork\n", progname); return; } else if (pid > 0) return; } else { com += 5; } close (ConnectionNumber (dpy)); execl (shell, sh_base, "-c", com, NULL); execl ("/bin/sh", "sh", "-c", com, NULL); _exit (1); } /* reap --- collect dead children */ void reap (int s) { (void) wait ((int *) NULL); signal (s, reap); } /* usage --- print a usage message and die */ void usage (void) { fprintf (stderr, "usage: %s [-display displayname] [-font fname] ", progname); fprintf (stderr, "[-file filename] [-path]"); fprintf (stderr, "[-geometry geom] [-shell shell] [-label name] "); fprintf (stderr, "[-popup] [-popdown] [-iconic] [-teleport] "); fprintf (stderr, "[-warp] menitem:command ...\n"); exit (0); } /* run_menu --- put up the window, execute selected commands */ void run_menu (void) { XEvent ev; XClientMessageEvent *cmsg; KeySym key; int i, cur, old, wide, high, ico, dx, dy; dx = 0; for (i = 0; i < numitems; i++) { wide = XTextWidth (font, labels[i], strlen (labels[i])) + PADX; if (wide > dx) dx = wide; } wide = dx; old = cur = -1; high = font->ascent + font->descent + PADY; dy = numitems * high; set_wm_hints (wide, dy); ask_wm_for_delete (); #define MenuMask (ButtonPressMask|ButtonReleaseMask\ |LeaveWindowMask|PointerMotionMask|ButtonMotionMask\ |ExposureMask|StructureNotifyMask|KeyPressMask) XSelectInput (dpy, menuwin, MenuMask); XMapWindow (dpy, menuwin); ico = 1; /* warp to first item */ i = 0; /* save menu Item position */ for (;;) { XNextEvent (dpy, &ev); switch (ev.type) { default: fprintf (stderr, "%s: unknown ev.type %d\n", progname, ev.type); break; case ButtonRelease: /* ignore mouse wheel */ if (ev.xbutton.button == Button4 || ev.xbutton.button == Button5) break; i = ev.xbutton.y / high; if (ev.xbutton.x < 0 || ev.xbutton.x > wide) break; else if (i < 0 || i >= numitems) break; if (warp) restoremouse (); if (strcmp (labels[i], "exit") == 0) { if (commands[i] != labels[i]) { spawn (commands[i]); } return; } spawn (commands[i]); if (popup) return; if (cur >= 0 && cur < numitems) XFillRectangle (dpy, menuwin, gc, 0, cur * high, wide, high); if (popdown) XIconifyWindow (dpy, menuwin, screen); cur = -1; break; case ButtonPress: case MotionNotify: old = cur; cur = ev.xbutton.y / high; if (ev.xbutton.x < 0 || ev.xbutton.x > wide) cur = -1; else if (cur < 0 || cur >= numitems) cur = -1; if (cur == old) break; if (old >= 0 && old < numitems) XFillRectangle (dpy, menuwin, gc, 0, old * high, wide, high); if (cur >= 0 && cur < numitems) XFillRectangle (dpy, menuwin, gc, 0, cur * high, wide, high); break; case KeyPress: key = XKeycodeToKeysym (dpy, ev.xkey.keycode, 0); if (key != CONFIG_MENU_UP_KEY && key != CONFIG_MENU_CANCEL_KEY && key != CONFIG_MENU_DOWN_KEY && key != CONFIG_MENU_SELECT_KEY) break; if (key == CONFIG_MENU_CANCEL_KEY) return; if (key == CONFIG_MENU_UP_KEY) { old = cur; cur--; } else if (key == CONFIG_MENU_DOWN_KEY) { old = cur; cur++; } while (cur < 0) cur += numitems; cur %= numitems; if (key == CONFIG_MENU_UP_KEY || key == CONFIG_MENU_DOWN_KEY) { if (cur == old) break; if (old >= 0 && old < numitems && cur != -1) XFillRectangle (dpy, menuwin, gc, 0, old * high, wide, high); if (cur >= 0 && cur < numitems && cur != -1) XFillRectangle (dpy, menuwin, gc, 0, cur * high, wide, high); break; } if (warp) restoremouse (); if (key == CONFIG_MENU_SELECT_KEY) { if (strcmp (labels[cur], "exit") == 0) { if (commands[cur] != labels[cur]) { spawn (commands[cur]); } return; } spawn (commands[cur]); } if (popup) return; if (popdown) XIconifyWindow (dpy, menuwin, screen); break; case LeaveNotify: cur = old = -1; XClearWindow (dpy, menuwin); redraw (cur, high, wide); break; case ReparentNotify: case ConfigureNotify: /* * ignore these, they come from XMoveWindow * and are enabled by Struct.. */ break; case UnmapNotify: ico = 1; XClearWindow (dpy, menuwin); break; case MapNotify: if (ico) { if (teleport) teleportmenu (i, wide, high); else if (warp) warpmouse (i, wide, high); } XClearWindow (dpy, menuwin); redraw (cur = i, high, wide); ico = 0; break; case Expose: XClearWindow (dpy, menuwin); redraw (cur, high, wide); break; case ClientMessage: cmsg = &ev.xclient; if (cmsg->message_type == wm_protocols && cmsg->data.l[0] == wm_delete_window) return; case MappingNotify: /* why do we get this? */ break; } } } /* set_wm_hints --- set all the window manager hints */ void set_wm_hints (int wide, int high) { Pixmap iconpixmap; XWMHints *wmhints; XSizeHints *sizehints; XClassHint *classhints; XTextProperty wname, iname; if ((sizehints = XAllocSizeHints ()) == NULL) memory ("size hints"); if ((wmhints = XAllocWMHints ()) == NULL) memory ("window manager hints"); if ((classhints = XAllocClassHint ()) == NULL) memory ("class hints"); /* fill in hints in order to parse geometry spec */ sizehints->width = sizehints->min_width = sizehints->max_width = wide; sizehints->height = sizehints->min_height = sizehints->max_height = high; sizehints->flags = USSize | PSize | PMinSize | PMaxSize; if (XWMGeometry (dpy, screen, geometry, "", 1, sizehints, &sizehints->x, &sizehints->y, &sizehints->width, &sizehints->height, &sizehints->win_gravity) & (XValue | YValue)) sizehints->flags |= USPosition; /* override -geometry for size of window */ sizehints->width = sizehints->min_width = sizehints->max_width = wide; sizehints->height = sizehints->min_height = sizehints->max_height = high; if (XStringListToTextProperty (&labelname, 1, &wname) == 0) memory ("window name structure"); if (XStringListToTextProperty (&labelname, 1, &iname) == 0) memory ("icon name structure"); menuwin = XCreateSimpleWindow (dpy, root, sizehints->x, sizehints->y, sizehints->width, sizehints->height, 1, black, white); iconpixmap = XCreateBitmapFromData (dpy, menuwin, (char *) nine_menu_bits, nine_menu_width, nine_menu_height); wmhints->icon_pixmap = iconpixmap; wmhints->input = False; /* no keyboard input */ if (iconic) wmhints->initial_state = IconicState; else wmhints->initial_state = NormalState; wmhints->flags = IconPixmapHint | StateHint | InputHint; classhints->res_name = progname; classhints->res_class = "larsmenu"; #ifdef SET_PROPERTIES_MANUALLY /* * For some reason, XSetWMProperties (see below) is failing * John O'Donnell replaces it with the following commands * (this leaves out XSetWMClientMachine, * and also environment variable checking from ClassHint) */ XSetWMName (dpy, menuwin, &wname); XSetWMIconName (dpy, menuwin, &iname); XSetCommand (dpy, menuwin, g_argv, g_argc); XSetWMHints (dpy, menuwin, wmhints); XSetClassHint (dpy, menuwin, classhints); XSetWMNormalHints (dpy, menuwin, sizehints); #else XSetWMProperties (dpy, menuwin, &wname, &iname, g_argv, g_argc, sizehints, wmhints, classhints); #endif } /* ask_wm_for_delete --- jump through hoops to ask WM to delete us */ void ask_wm_for_delete (void) { int status; wm_protocols = XInternAtom (dpy, "WM_PROTOCOLS", False); wm_delete_window = XInternAtom (dpy, "WM_DELETE_WINDOW", False); status = XSetWMProtocols (dpy, menuwin, &wm_delete_window, 1); if (status != True) fprintf (stderr, "%s: could not ask for clean delete\n", progname); } /* redraw --- actually redraw the menu */ void redraw (int cur, int high, int wide) { int tx, ty, i; for (i = 0; i < numitems; i++) { tx = (wide - XTextWidth (font, labels[i], strlen (labels[i]))) / 2; ty = i * high + font->ascent + (PADY / 2); XDrawString (dpy, menuwin, gc, tx, ty, labels[i], strlen (labels[i])); } if (cur >= 0 && cur < numitems) XFillRectangle (dpy, menuwin, gc, 0, cur * high, wide, high); } /* teleportmenu --- move the menu to the right place */ void teleportmenu (int cur, int wide, int high) { int x, y, dummy; Window wdummy; if (XQueryPointer (dpy, menuwin, &wdummy, &wdummy, &x, &y, &dummy, &dummy, (unsigned int *) &dummy)) XMoveWindow (dpy, menuwin, x - wide / 2, y - cur * high - high / 2); } /* warpmouse --- bring the mouse to the menu */ void warpmouse (int cur, int wide, int high) { int dummy; Window wdummy; int offset; /* move tip of pointer into middle of menu item */ offset = (font->ascent + font->descent + 1) / 2; offset += 6; /* fudge factor */ if (XQueryPointer (dpy, menuwin, &wdummy, &wdummy, &savex, &savey, &dummy, &dummy, (unsigned int *) &dummy)) XWarpPointer (dpy, None, menuwin, 0, 0, 0, 0, wide / 2, cur * high - high / 2 + offset); } /* restoremouse --- put the mouse back where it was */ void restoremouse (void) { XWarpPointer (dpy, menuwin, root, 0, 0, 0, 0, savex, savey); } larswm-7.5.3/larsmenu.man0000644000000000000000000001120610065667625015331 0ustar rootroot00000000000000.TH LARSMENU 1x .SH NAME larsmenu \- create a menu to run commands .SH SYNOPSIS .B larsmenu [ .BI \-bg " background-color" ] [ .BI \-display " displayname" ] [ .BI \-file " name" ] [ .BI \-fg " foreground-color" ] [ .BI \-font " fname" ] [ .BI \-geometry " geom" ] [ .B \-iconic ] [ .BI \-label " name" ] [ .B \-path ] [ .B \-popdown ] [ .B \-popup ] [ .BI \-shell " prog" ] [ .B \-teleport ] [ .B \-version ] [ .B \-warp ] .IR menuitem [: command ] \&... .SH DESCRIPTION larsmenu is a simple program that accepts a list of menu item and command pairs on the command line. It creates a window that consists of nothing but a menu. When a particular item is selected, the corresponding command is executed. .PP Any mouse button may be used to select an item. Alternatively, the UP-ARROW and DOWN-ARROW cursor keys may be used to highlight different items, with ENTER used to select the highlighted item. ESCAPE exits the menu without selecting an entry. .PP Menu items and commands are separated by a colon. The colon and command are optional. If they are missing, then the menu item is assumed to be a command that can be executed directly. .PP A menu item consisting of the word .B exit causes larsmenu to exit when it is selected. Otherwise, to stop larsmenu, delete it using the window manager. If a command is supplied along with the .B exit item, that command is executed before larsmenu exits. .PP If a command starts with the word .BR exec , larsmenu ceases operating after launching it. .PP larsmenu accepts the following command line options, listed alphabetically: .RS .TP .BI \-bg " background-color" Set the background color to .IR background-color . By default, the background color is white. .TP .BI \-display " displayname" Use the X display .IR displayname , instead of the default display. .TP .BI \-file " filename" Read items to display from .IR filename , in addition to any other command line arguments. This is intended for use with .B #! in scripts. .TP .BI \-fg " foreground-color" Set the foreground color to .IR foreground-color . By default, the foreground color is black. .TP .BI \-font " fname" Use the font .IR fname , instead of fixed. .TP .BI \-geometry " geom" Use .I geom (a geometry in standard X format) as the geometry of the menu. This is most useful for specifying the initial location of the menu. Note that larsmenu overrides the size part of the geometry specification. The window is always just large enough to hold the menu. .TP .B \-iconic Start up in the iconified state. .TP .BI \-label " name" Change both the window and icon labels of the window to .IR name . .TP .B \-path Append the current directory to the command search path. .TP .B \-popdown Once an item is selected, the menu window automatically iconifies itself. .TP .B \-popup Act like a pop-up menu. Once a menu item is selected, larsmenu exits. This option overrides .BR \-popdown . .TP .BI \-shell " prog" Use .I prog as the shell to run commands, instead of .BR /bin/sh . If the shell cannot be executed, larsmenu then silently falls back to using .BR /bin/sh . .TP .B \-teleport Move the menu to where the mouse is when the menu is uniconified. This option is particularly useful when combined with .BR \-popdown . .TP .B \-version This option prints the version of larsmenu on the standard output, and then exits with an exit value of zero. .TP .B \-warp Warp the mouse to the menu when the menu is uniconified. After the selection is made, restore the mouse to where it was. This option is particularly useful when combined with .BR \-popdown . .RE .SH EXAMPLE .ft B .nf larsmenu -popup "XTerm:xterm" "Calculator:xcalc" .ft .fi .SH LICENSE This is a modified version of 9menu, which has this license: --- 9menu is free software, and is Copyright (c) 1994 by David Hogan and Arnold Robbins. Permission is granted to all sentient beings to use this software, to make copies of it, and to distribute those copies, provided that: (1) the copyright and licence notices are left intact (2) the recipients are aware that it is free software (3) any unapproved changes in functionality are either (i) only distributed as patches or (ii) distributed as a new program which is not called 9menu and whose documentation gives credit where it is due (4) the authors are not held responsible for any defects or shortcomings in the software, or damages caused by it. There is no warranty for this software. Have a nice day. --- Please consider my code to be under the same type of license as 9menu, inserting my name where appropriate. .SH SEE ALSO larsclock(1x), larsremote(1x), larswm(1x) .SH AUTHORS larsmenu was created by Lars Bernhardsson by building on 9menu by David Hogan and Arnold Robbins. larswm-7.5.3/larsremote.c0000644000000000000000000000432610065667625015334 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ #include #include #include #include #include #include #include #include Display *dpy; Atom exit_larswm; Atom restart_larswm; Atom bartext_larswm; void usage (void) { fprintf (stderr, "usage: larsremote [-display display] \n"); exit (1); } void sendcmessage (Window w, Atom a, long x, int isroot) { XEvent ev; long mask; memset (&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = a; ev.xclient.format = 32; ev.xclient.data.l[0] = x; ev.xclient.data.l[1] = CurrentTime; mask = 0L; if (isroot) mask = SubstructureRedirectMask; /* magic! */ XSendEvent (dpy, w, False, mask, &ev); } int main (int argc, char **argv) { int i, do_exit, do_restart, do_message; char *display_string = ""; char *msgtext; do_exit = do_restart = do_message = 0; for (i = 1; i < argc; i++) { if ((strcmp (argv[i], "-display") == 0) && (i + 1 < argc)) { display_string = argv[++i]; } else if (strcmp (argv[i], "exit") == 0) { do_exit++; } else if (strcmp (argv[i], "restart") == 0) { do_restart++; } else if (strcmp (argv[i], "message") == 0) { msgtext = argv[++i]; do_message++; } else { usage (); } } if ((do_exit + do_restart + do_message) != 1) usage (); dpy = XOpenDisplay (display_string); if (dpy == 0) { perror ("XOpenDisplay"); exit (1); } exit_larswm = XInternAtom (dpy, "LARSWM_EXIT", False); restart_larswm = XInternAtom (dpy, "LARSWM_RESTART", False); bartext_larswm = XInternAtom (dpy, "LARSWM_BARTEXT", False); if (do_exit) { sendcmessage (DefaultRootWindow (dpy), exit_larswm, 0L, 1); } else if (do_restart) { sendcmessage (DefaultRootWindow (dpy), restart_larswm, 0L, 1); } else if (do_message) { XTextProperty pr; XStringListToTextProperty (&msgtext, 1, &pr); XSetTextProperty (dpy, DefaultRootWindow (dpy), &pr, bartext_larswm); XFree (pr.value); } XSync (dpy, False); exit (0); } larswm-7.5.3/larsremote.man0000644000000000000000000000166510065667625015670 0ustar rootroot00000000000000.TH larsremote 1x .SH NAME larsremote \- Command line control for larswm .SH SYNOPSIS .B larsremote [ .B \-display .I dpy ] .B message .I text .B | exit | restart .SH DESCRIPTION .I larsremote lets you control the larswm window manager from the command line. .SH OPTIONS The following command line options are supported: .TP 18 .BI \-display " dpy" lets you specify which display you want to open. .TP 18 .BI message " text" Sends text to the running .I larswm to be displayed on the status bar. .TP 18 .B exit tells the running .I larswm to exit gracefully. This is the normal way to log out if your session hangs on the window manager. .TP 18 .B restart tells the running .I larswm to restart. Use this if you have updated your preferences file and want the new preferences to take effect without first logging out. .SH SEE ALSO larsclock(1x), larsmenu(1x), larswm(1x) .SH AUTHORS .I larsremote was created by Lars Bernhardsson . larswm-7.5.3/larswm.man0000644000000000000000000007336210070132076015002 0ustar rootroot00000000000000.TH larswm 1x .SH NAME larswm \- Tiling Window Manager for X .SH SYNOPSIS .B larswm [ .B \-display .I dpy ] [ .B \-f .I file ] [ .B \-defaults ] [ .B \-v ] .SH DESCRIPTION larswm is a tiling window manager for X11, based on 9wm by David Hogan. It provides virtual desktops, support for tiled and untiled windows, keyboard shortcuts and more, while using very little system resources. Please see http://larswm.fnurt.net for more information. .SH OPTIONS The following command line options are supported: .TP 18 .BI \-display " dpy" lets you specify which display you want larswm to manage. .TP 18 .BI \-f " file" lets you specify a preferences file other than $HOME/.larswmrc to use for configuration. .TP 18 .B \-defaults prints to standard out a complete resource file for larswm containing all options and their defaults. .TP 18 .B \-v prints the current version on standard error, then exits. .SH FILES .TP 18 .B $HOME/.larswmrc /etc/X11/larswmrc these two files are looked for in the above order when larswm starts up. .SH The Idea When I started working on larswm I had a few ideas that I think are important in a window manager. They are as follows: 1. The user should not have to spend alot of time arranging windows on the screen, leaving more time for the actual work that he or she is trying to accomplish. 2. Direct manipulation. Instead of accessing windows and desktops through representations of these, access them directly. That means: No icons when a window is iconified. No graphical map of the virtual desktops, larswm is fast enough that it is easier to browse the actual desktops instead, something that is very quick and easy to do, especially if you have a wheel mouse, and since the windows are tiled, you usually do not need much time looking at a desktop to know what is on it. And within one desktop, tiling is a good example of direct manipulation, a common way to deal with multiple windows on the screen is to overlap them and select which one you want my clicking on a representation in the form of a button on a task bar, however, larswm does not need that because the actual window, with enough content visible to know which one it is, is always visible. 3. No precision clicking. Use the edges of the monitor to make it easy to aim with the mouse pointer. 4. It must be predictable. If the user ever wonders how focus ended up on a window that he or she did not click on, something is wrong. larswm has alot of code that deals with figuring out where focus should go when different events occur. 5. It must have a solid feel to it. Part of this is speed, when you switch desktops or windows are moved around as the result of being tiled it must go quick, and part of it is predictability. 6. The window manager should not use more system resources (CPU time, virtual memory) than is absolutely necessary for performing the task of managing windows. The GUI is minimal, providing borders around the windows, and a status bar at the bottom of the screen. It provides all feedback using plain text on the status bar. 7. Quality control. It has been tested with Electric Fence to catch memory access errors and profiled with gprof. So far I have been able to fix everything that I found with these tools, but I am no CS major and I am sure some things could be done better. Nevertheless, it works, and during normal circumstances it works using minimal system resources. .SH Terminology Some of this is unique to larswm and some is borrowed from other GUI designs. .I Screen Physical monitor. By default larswm will use up to 4 monitors. This can be adjusted in the dat.h file. .I Virtual Desktop Each screen is logically divided into up to 16 workspaces. A window is usually only visible on one of these workspaces. .I Subdesktop Each virtual desktop is then logically divided between two subdesktops. First we have normal, untiled, windows. They are managed in a way similar to most other window managers. Second we the tiled subdesktop, where no window is allowed to overlap another. Switching between the tiled and the untiled set of windows is very fast with a hotkey or mouse click. .I Track On the tiled subdesktop, windows are laid out in one of two tracks. By default, the ratio is 60%/40% for left/right track. The ratio can be changed dynamically through hotkeys, and a different default can be set in the .larswmrc file. The left track always contains one window filling it from top to bottom while the right track contains any other windows, evenly sized. There are hotkeys to make any window in the right track expand and move to the left track while the window that was in the left track is shrunk and placed at the top of the right track. .I Status Bar The status bar fills two functions. First off, as the name implies, it shows status messages. This includes the window title of the focused window, the selected virtual desktop, flags that shows what modes are set on the current virtual desktop and a user defined message that is used by the sample clock app to show the current date and time. Second, it is a very big button that can be clicked to perform various functions. It is easy to target, since you just move the mouse down against the bottom of the screen, no need to precision aim for it. .I Tool A special kind of window that belongs to the untiled subdesktop, but is still tiled around. It is also visible on all virtual desktops. Used for things like clocks and load meters. .I Select Zoom Maximize a window so that the height/width ratio is the same as for a US letter sized paper, and centering it on the screen. Besides wanting to tile windows, this was the most common manual move/resize operation I used before it was automated. .I Put Aside All this means is that a window is moved mostly off screen, leaving just a portion visible. It is another way to do iconification. .SH A Sample Session The following assumes you are using the sample.xsession and sample.larswm config files. After logging in, you will see a mostly empty desktop. Along the bottom of the screen is the status bar, and in the lower right corner are three smaller windows (xload, xbiff and xclock) which in the default config are tagged as tool windows. What this means is they should be visible on all virtual desktops, and should not be covered by windows that are placed automatically on the tiled subdesktop. .B Working with tiled windows Now hit Shift-Control-Return. This will bring up a new terminal window. Notice how it occupies the left 60% of the screen. Type something in this window and hit Shift-Control-Return again. The first window is moved to the right side and shrunk, while the new xterm occupies the bigger area to the left. Notice that the toolwindows (xload, xbiff and xclock) are not overlapped. Hit Shift-Control-Return once more and notice how the two previous windows now both are on the right side and using half the space each. Now hit Control-Button1 on the first window you opened, it should be the xterm right above the tool windows on the right side. This will put that window in the left track, while putting the left track window at the top of the right track. That is all there is to never having to manually line up your xterms again! .B Working with untiled windows For demonstration purposes, we can use xlogo. By default, the xlogo window class is not set to be tiled, so it will be opened on the untiled subdesktop, separate from all the xterms. In the focused xterm, type xlogo and hit Return. The xlogo window should appear in the middle of the screen above the tiled windows. If you need to switch between tiled and untiled windows, you can use Shift-Control-BackSpace. Hit that key twice and see how xlogo is first hidden behind the tiled xterms and then brought to the front again. If you had more untiled windows open, they would all have been lowered and raised together. .B Moving windows to predefined areas You can move untiled windows to 9 different predefined locations on the screen with only one keystroke. With the xlogo window focused, hit Shift-Control-KP_6. The xlogo window should be against the right edge of the screen, halfway between the top and bottom, just like 6 on the numeric keypad is among the keys 1 through 9. Hit Shift-Control and each number on the numeric keypad to see the locations. When done, leave the window on the right edge in the middle (Shift-Control-KP_6). .B Select zooming With the xlogo window focused and off to the side of the screen, hit Shift-Control-space. Notice how it is centered and sized to make it easy to work with. When you hit Shift-Control-space again, it is returned to its former place and size. This can be used as an alternative to tiling, if you have some windows you would like to mostly manage yourself, but want a quick way to concentrate on one of them. .B Set aside windows Sometimes when working on the untiled desktop you just want to set a window aside for a moment. Hit Control-Alt-space to move a window sideways off the right edge of the screen, leaving just a small portion visible. Clicking on the visible part will put that window back where it was. If you hit Control-Alt-space with no untiled window focused, the last put aside window will be brought back. See the mouse reference section for more ways to manipulate windows in this fashion. .B Using the mouse to move and resize windows With the xlogo window unzoomed and focused, move the mouse down onto the status bar, anywhere will do, and hold down Shift-Alt-Button1. The mousepointer moved to the top left corner of the window and you are able to move the window around by moving the mouse. To place the window, let go of the mouse button. Move xlogo to somewhere near the top left of the screen. Next, with the mouse on the status bar, hold down Shift-Control-Alt-Button1. The mouse pointer is moved to the bottom right corner of the xlogo window and when you move the mouse, you resize the window. To set the size, let go of the mouse button. .B Moving a window between subdesktops Make sure the xlogo window is focused and then hit Shift+Alt+space. The xlogo should now be tiled and focused in the left track. If you hit Shift+Alt+space once more, it becomes untiled again and the other tiled windows moves to fill the vacated spot in the left track. .B Working with virtual desktops So far, we have only used the first desktop. The way to switch between desktops is easy. Shift-Control-Left and Shift-Control-Right on the keyboard will move you back and forth between the desktops. Hit Shift-Control-Right four times. Notice how the status bar label changes to show what desktop is active. By default there are four virtual desktops per screen, so you should be back to the first desktop now. If you instead use Shift-Alt-Left or Shift-Alt-Right you will move to the new virtual desktop while dragging the currently focused window with you. .B Using the mouse wheel With larswm, the mouse wheel can be used for quite a few operations. The most common is to switch virtual desktop. This can be done by moving the pointer to the status bar and rolling the wheel up and down. You can also use the mouse wheel to move and resize windows quickly. With xlogo focused, move the pointer to the status bar and hold down Shift-Alt while rolling the wheel to move the window sideways. If you hold down Shift-Control-Alt you move the window up and down, and with Shift-Control you can grow and shrink the window. If you have more than one window open, hold down Shift while rolling the wheel down to cycle focus through each window. To try it now, shift to the tiled subdesktop by clicking on any of the tiled xterms then move the mouse pointer to the status bar, hold down shift and roll the wheel. This is not exactly intuitive, but very fast once you learn the combinations of Shift, Control and Alt keys to do these things. .SH Status Bar Menu System The status bar is used for a simple menu system. With the pointer on the status bar, hold down Control and click Button1 and Button3, or roll the wheel up and down, to scroll between the menu entries. Control-Button2 selects the current menu entry, usually toggling a desktop or window setting. If you instead of Control hold down Alt, you can scroll through the list of iconified windows, and Alt-Button2 uniconifies the selected window. .SH Things You Can Configure You can affect alot (but not all!) of the behaviour of larswm by making your own .larswmrc file and putting it in your home directory. .B Default setup Included in the distribution files is a file called sample.larswmrc that you can use as a starting point for your own config. .B Complete list of config keywords Another way to get a default .larswmrc is to run larswm with the -defaults flag. It will print out all the possible options with their defaults filled in, all you have to do is uncomment and edit any lines you wish to change. Rather than reproduce that here, you can create your own up to date version by running the command larswm -defaults and piping it to a file. .SH Keyboard commands for all windows and subdesktops .TS allbox; l l l. Shift-Control Prior Prev Screen Shift-Control Next Next Screen Shift-Control Left Prev Desktop Shift-Alt Left Prev Desktop Drag Focused Window Shift-Control Right Next Desktop Shift-Alt Right Next Desktop Drag Focused Window Shift-Control F1-F12 Jump to desktop 1-12 Shift-Control BackSpace Toggle Subdesktop Shift-Control Up Prev Window Shift-Control Down Next Window Control-Alt z Hide Window Control-Alt x Unhide last hidden window Control-Alt w Close Window Shift-Alt space Move window to other subdesktop .TE .PP .SH Keyboard commands for untiled windows .TS allbox; l l l. Shift-Control space Select Zoom Control-Alt space Put/restore aside window Shift-Control 0 Put aside all other windows Shift-Control KP_Home Move window to top left Shift-Control KP_Up Move window to top center Shift-Control KP_Prior Move window to top right Shift-Control KP_Left Move window to left center Shift-Control KP_Begin Center window Shift-Control KP_Right Move window to right center Shift-Control KP_End Move window to bottom left Shift-Control KP_Down Move window to bottom center Shift-Control KP_Next Move window to bottom right Shift-Alt KP_Up Move window up Shift-Alt KP_Down Move window down Shift-Alt KP_Left Move window left Shift-Alt KP_Right Move window right Shift-Control-Alt KP_Up Grow window vertically Shift-Control-Alt KP_Down Shrink window vertically Shift-Control-Alt KP_Left Shrink window horizontally Shift-Control-Alt KP_Right Grow window horizontally Shift-Control-Alt KP_Home Grow window both ways Shift-Control-Alt KP_End Shrink window both ways Shift-Alt KP_Insert Toggle move/resize increment Shift-Alt KP_Home Maximize window vertically Shift-Alt KP_End Maximize window horizontally Shift-Alt KP_Begin Maximize window Shift-Control-Alt KP_Begin Full screen .TE .PP .SH Keyboard commands for tiled windows .TS allbox; l l l. Shift-Control-Alt KP_Up Maximize left track Shift-Control-Alt KP_Down Restore left track Shift-Control-Alt KP_Left Shrink left track Shift-Control-Alt KP_Right Grow left track Shift-Alt KP_Begin Move window to/from left track Control-Alt space Restore aside window .TE .PP .SH Mouse buttons on the status bar .TS allbox; c c c c l l l l. Modifier Button1 Button2 Button3 None Prev Desktop Subdesktop Next Desktop Control Prev Menu Select Menu Next Menu Alt Prev Hidden Hide/Unhide Next Hidden Shift-Control Shrink Select Zoom Grow Shift-Alt Move Window Shift-Control-Alt Resize Window Lower Window Maximize Window Control-Alt Restore Aside Put/Restore Aside Put Aside .TE .PP .SH Mouse wheel on the status bar .TS allbox; c c c l l l. Modifier Roll Up Roll Down None Prev Desktop Next Desktop Shift Prev Window Next Window Control Prev Menu Next Menu Alt Prev Hidden Next Hidden Shift-Control Shrink Grow Shift-Alt Move Up Move Down Shift-Control-Alt Move Left Move Right Control-Alt Restore Aside Put Aside .TE .PP .SH Clicking on unfocused windows Button1 is used to focus windows. If skip_focus is on (this is the default) you can force a tiled window into the left track by Control-Button1 clicking. If skip_focus is off, then Control-Button1 clicking will prevent moving the newly focused window to the left track. If you Control-Button1 click on a window that is not on the active subdesktop, you will switch focus without also switching subdesktop. If you Control-Button1 click on an aside window, that window will be put back while all other untiled windows are put aside. .SH Indexed resources In the sample.larswmrc, all the entries that end in a number are indexed resources. The number can be between 0 and 63, and must be unique within each resource type. .SH Multi-head When specifying an option that only affects one of the virtual desktops, you can also limit it to a specific monitor. For instance, larswm.0.0.dtname: One would name the first virtual desktop on the first monitor only. Due to precedence, you can set an option for all desktops one way, and then specific desktops another. The ways to specify screens and desktops are, listed in order of precedence: .TS allbox; c c l l. Format Affected desktops/screens larswm.S.D.resource Only desktop D on screen S larswm.S.?.resource All desktops on screen S larswm.?.D.resource Only desktop D on all screens. larswm.?.?.resource All desktops on all screens. larswm*resource All desktops on all screens. .TE .PP As an example, if you want all desktops except the first on the second monitor to not resize windows that are tiled, you would put the following lines in your .larswmrc: larswm*tile_resize: false larswm.1.0.tile_resize: true The first line is needed because the default is to resize windows. .SH The Status Bar The thin window across the bottom of the screen is the status bar. On the left is the window title of the focused window, and on the right is a status area. .B Mode flags Between the virtual desktop label and the user defined message (date/time in the default setup) is a block of flags in upper case [TCRSBH]. They indicate the following: .IB T " Subdesktop" T for tiled or U for untiled. .IB C " Clickthru" Whether clicks on an unfocused window should focus and pass the click on to the client, or just focus and discard the click. C means pass to client. .IB R " Tile Resizing" Whether tiled windows are resized or not. R means they are resized. If not, they are just stacked in the right track, each having the top left corner visible. .IB S " Skip Focus" Whether giving focus to a window in the right track makes it jump to the left track. S means no, you have to Control-Button1 click it to make it jump. If off, you can Control-Button1 click to make a window stay in place while getting focus. .IB B " Big Move/Resize" Whether the keyboard and mouse wheel commands to move and resize windows should work a pixel at a time, or 5% of the screen width/height at a time. .IB H " Hidden Windows" Whether any windows are hidden (iconified) on any screens. It is there so you will not forget about them, since larswm has no visual representation of iconified windows. .B Window mode flags The status bar will also show the class of the focused window and instance in the format (Class~Instance). Just to the right of that is another set of flags in lower case [nftsz] that mean: .IB n " Notile" Window belongs to the untiled subdesktop. .IB f " Floating" Window always stays on top of non-floating windows. .IB t " Tool" Window is tiled around, not over. .IB s " Sticky" Window is visible on all virtual desktops. .IB z " Zoomed" Window is in one of the zoomed states. .B User defined message If you want, you can put any message you like in the right most portion of the status bar. This can be used for things like clocks, email notifiers, stock tickers etc. Included in the distribution is a small example of a clock called larsclock. It is started by the default session script. If you do not run larsclock, you can set the message from any shell script with the command larsremote message TEXT, which would show TEXT on the status bar. .SH Window Types Here is a more detailed look at the different types larswm can associate with a window. .B Transient windows Windows that have the WM_TRANSIENT_FOR property set are put on the untiled subdesktop even if the window class has been specified as tiled. When a transient window first gets mapped, it will always show up, no matter what desktop you are viewing. The transient window will be assigned to the desktop where the parent window is though, so as soon as you change desktop, it will only show up on the virtual desktop the parent belongs to. .B Untiled windows Any window that is not tiled is assigned to the untiled subdesktop. These windows are completely separate from the tiled subdesktop. The untiled subdesktop behaves more or less like any traditional window manager, but adds a few keyboard shortcuts for moving windows to different parts of the screen or zooming them in both dimensions. larswm will not tile a window unless its class/instance can be found in the larswm.dotileclass list. The way to move between your tiled and untiled desktop is through a keyboard shortcut, which by default is Shift-Control-BackSpace When a window is mapped on the untiled subdesktop for the first time, it is centered on the screen, unless it has had its desired position set in the hints. .B Floating windows Floating windows will always stay on top of other non-floating windows, regardless of which subdesktop is active. This can be used for small windows, like xcalc, that you always want accessible. If clickthru is on, clicks will be passed on to floating windows regardless of which subdesktop was active before the click. .B Sticky windows Sticky windows are windows of a class and instance that matches an entry in the larswm.stickyclass list. They are always visible no matter which virtual desktop you are on. .B Tools Tools are windows you always want visible. Examples of tools are xclock, xload and other small informational windows. When a window has been identified as a tool window, it will be assigned to the untiled desktop, it will be sticky and the tiled windows will not cover it. Also, if clickthru is on, any clicks on tool windows will be passed on to the client, regardless of which subdesktop was active before the click. Tools will never end up focused unless you click on them. .SH Internals A little more detail about how larswm does things. Every time a window is mapped or unmapped, or (if skip_focus is off) you focus a new window on the tiled subdesktop by clicking on it the following process is executed: 1. The width of the two tracks are calculated. This is by default set up so the left track uses 60% of the screen width, but it can be configured in the .larswmrc file. 2. It calculates how many windows should be in each track, one in the left track and the rest in the right. 3. The height of each window in each track is calculated. 4. It goes through the list of all windows and places them in the designated spot. 5. After this it returns to the event loop. That is pretty much it. If skip_focus is off (default is on), when you click on an inactive window in the right track, it will pop over into the left track, and the window that were there will pop over to the top of the right track. At all times, the right track will contain tiled windows in the order that they were in the left track, starting with most recent. .SH Associating windows with a virtual desktop You can associate certain window classes/instances to a certain virtual desktop number by adding resources to your .larswmrc. An example of how to associate all Netscape windows with the second virtual desktop: larswm.dtclass.0: Netscape larswm.dtnum.0: 1 When any Netscape window opens, larswm will first switch to the specified desktop, then map the window. .SH Hidden windows larswm iconifies windows by hiding them. To unhide a hidden window, you must first locate its label using the status bar. Please see the section about using menus on the status bar for information on how this works. You can also unhide the last hidden window with one keystroke, Control-Alt-x. .SH Focus handling To change focus to a window, you just left click on it, and if skip_focus is off that window will pop into the left track, and the window currently there will pop over to the top of the right track. If you have it set up to automatically put the focused window in the left track, you might still sometimes want to type something into one of the tiled windows without rearranging all the windows, and to do that you Control-Button1 click on a window. Focus will change, but all windows will stay where they are. This will also prevent any transient windows owned by the application from immediately be raised and get focus. If you have it in the default mode, where selecting a new window to have focus does not make it pop into the left track you can do that by Control-Button1 clicking it. .SH Clickthru When you click on a window to give it focus, that click is also passed on to the client. This makes it easier to work with a multi-window application. You can turn this feature off, in which case the click used to focus a window is never seen by the application. .SH Multi-Head When a window gets mapped, for whatever reason, it is usually given focus. But if the MapRequest event occurs on a different screen than the one you are working on, things could get confusing. I solved this by adding the following rules to how focus is assigned when windows open and close: 1. If the currently focused window is on the same screen, then the new window will get focus. 2. If the currently focused window is on a different screen, the new window will get focus only if the mouse pointer is on the same screen as the new window. 3. If no window is focused, a newly mapped window will get focus only if the mouse pointer is on the same screen as the new window. 4. If the focused window closes, focus will revert to another window, usually the window that was focused before the one that just closed. Focus will revert only if the mouse pointer is on the same screen as the window that closed. I believe these rules will help eliminate most cases of having your keystrokes go to a window you did not intend it to. .SH Atoms The following atoms are created and monitored by larswm and can be used in third party tools: .I LARSWM_EXIT Tells larswm to exit. .I LARSWM_RESTART Tells larswm to restart, reloading the .larswmrc file. .I LARSWM_BARTEXT When this is updated, the content of this atom is shown as text on the status bar until the atom is updated again. See larsclock and larsremote for examples of how to use this. .SH Compatibility .B Terminal Windows xterm windows might look like they are not redrawing correctly, but they are in fact. It is up to the program running inside it to detect window size changes and redraw the screen as necessary. One way to deal with this is to run screen inside the xterm, as it will handle resizing and redrawing correctly. On some, mostly older, systems you need to make terminal windows know that they have been resized when they are first opened and tiled. Put this line in your .cshrc or .bashrc: eval \`resize\` It will ensure that it is set to the correct number of rows and columns when it is opened. .B Size Hints The PResizeInc and PMaxSize hints are honored. PMinSize is not, as it might have problems fitting all the windows in when tiling them. .B Resizing Windows For windows that do not cope well with being resized, you can disable automatic resizing on a particular desktop, making the windows in the right track be stacked on top of eachother instead. This can also be used for windows that resize slowly, like Netscape, to speed things up considerably. .B Multi-Head Displays It does work well with multi-head displays. One of my development systems is a dual-head Sun running Solaris 9, so this functionality has been tested quite alot. It currently behaves in a predictable manner when you switch focus between screens, move between desktops etc. .B GTK Applications Some GTK apps do not set WM_TRANSIENT_FOR correctly on their dialog boxes, and they also sometimes have a different class string on those subwindows, making things confused. The best way to deal with those kinds of problems is to specify both the class and instance of the top level windows you do want tiled. In some cases, this still does not work, like in some builds of Mozilla where every window it creates has class/instance Mozilla-bin/mozilla-bin. .B Standards Compliance At this time there is no GNOME/KDE/Motif/whatever compatibility. It follows the ICCCM as much as it can while still providing all the automatic functionality that it does. .SH LICENSE Many thanks to David Hogan for writing 9wm and releasing it under such a license that I could use it as a base to build larswm on. Here is the original license for 9wm: --- 9wm is free software, and is Copyright (c) 1994-1996 by David Hogan. Permission is granted to all sentient beings to use this software, to make copies of it, and to distribute those copies, provided that: (1) the copyright and licence notices are left intact (2) the recipients are aware that it is free software (3) any unapproved changes in functionality are either (i) only distributed as patches or (ii) distributed as a new program which is not called 9wm and whose documentation gives credit where it is due (4) the author is not held responsible for any defects or shortcomings in the software, or damages caused by it. There is no warranty for this software. Have a nice day. --- Please consider my code to be under the same type of license as 9wm, inserting my name where appropriate. .SH SEE ALSO larsclock(1x), larsmenu(1x), larsremote(1x) .SH AUTHORS larswm was created by Lars Bernhardsson by building on 9wm by David Hogan. larswm-7.5.3/main.c0000644000000000000000000002423510075552233014071 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" Display *dpy; ScreenInfo *screens; int initting; XFontStruct *font; char **myargv; char *shell; Bool shape; int num_screens; Atom exit_larswm; Atom restart_larswm; Atom bartext_larswm; Atom wm_state; Atom wm_change_state; Atom wm_protocols; Atom wm_delete; Atom wm_colormaps; void usage (void) { fprintf (stderr, "%s\n", VERSION); fprintf (stderr, "usage: larswm [-display display] [-f file] [-defaults] [-v]\n"); exit (1); } int main (int argc, char **argv) { int i; int shape_event, dummy; char rcname[512]; char *display_string = ""; char *rc_file; rc_file = getenv ("HOME"); if (rc_file) { strncpy (rcname, rc_file, sizeof (rcname) - 11); strcat (rcname, "/.larswmrc"); rc_file = rcname; } myargv = argv; font = 0; for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-f") == 0 && i + 1 < argc) { rc_file = argv[++i]; } else if (strcmp (argv[i], "-display") == 0 && i + 1 < argc) { display_string = argv[++i]; } else if (strcmp (argv[i], "-defaults") == 0) { set_defaults (); dump_prefs (); exit (0); } else if (strcmp (argv[i], "-v") == 0) { fprintf (stderr, "%s\n", VERSION); exit (0); } else { usage (); } } shell = (char *) getenv ("SHELL"); if (shell == NULL) shell = DEFSHELL; dpy = XOpenDisplay (display_string); if (dpy == 0) fatal ("can not open display"); initting = 1; XSetErrorHandler (handler); exit_larswm = XInternAtom (dpy, "LARSWM_EXIT", False); restart_larswm = XInternAtom (dpy, "LARSWM_RESTART", False); bartext_larswm = XInternAtom (dpy, "LARSWM_BARTEXT", False); wm_state = XInternAtom (dpy, "WM_STATE", False); wm_change_state = XInternAtom (dpy, "WM_CHANGE_STATE", False); wm_protocols = XInternAtom (dpy, "WM_PROTOCOLS", False); wm_delete = XInternAtom (dpy, "WM_DELETE_WINDOW", False); wm_colormaps = XInternAtom (dpy, "WM_COLORMAP_WINDOWS", False); XrmInitialize (); load_prefs (rc_file); if (prefs.fname != 0) { if ((font = XLoadQueryFont (dpy, prefs.fname)) == 0) fprintf (stderr, "larswm: warning: can't load font %s\n", prefs.fname); } if (font == 0) { prefs.fname = "fixed"; if ((font = XLoadQueryFont (dpy, prefs.fname)) == 0) fatal ("can not find fixed font"); } shape = XShapeQueryExtension (dpy, &shape_event, &dummy); num_screens = ScreenCount (dpy); if (num_screens > MAXSCREENS) { fprintf (stderr, "larswm was compiled with support for %d screens.\n", MAXSCREENS); fprintf (stderr, "please recompile with MAXSCREENS set to at least %d screens.\n", num_screens); exit (1); } screens = (ScreenInfo *) malloc (sizeof (ScreenInfo) * num_screens); for (i = 0; i < num_screens; i++) initscreen (&screens[i], i); XSync (dpy, False); initting = 0; nofocus (); for (i = 0; i < num_screens; i++) scanwins (&screens[i]); initkeys (0); XSync (dpy, False); mainloop (shape_event); exit (0); } void initscreen (ScreenInfo * s, int i) { char *ds, *colon, *dot1; unsigned long mask; XGCValues gv; int t; s->num = i; s->root = RootWindow (dpy, i); s->def_cmap = DefaultColormap (dpy, i); s->min_cmaps = MinCmapsOfScreen (ScreenOfDisplay (dpy, i)); s->tile_height = s->res_height = DisplayHeight (dpy, s->num); ds = DisplayString (dpy); strcpy (s->display, "DISPLAY="); strcat (s->display, ds); colon = rindex (ds, ':'); if (colon && num_screens > 1) { colon = s->display + 8 + (colon - ds); dot1 = index (colon, '.'); if (!dot1) dot1 = colon + strlen (colon); sprintf (dot1, ".%d", i); } /* hey, this is experimental software, it doesn't have to look pretty just yet. :) */ if (prefs.fgstr) { XColor color; if (XAllocNamedColor (dpy, DefaultColormap (dpy, s->num), prefs.fgstr, &color, &color) == 0) { fprintf (stderr, "XAllocNamedColor - allocation of fg color failed.\n"); s->black = BlackPixel (dpy, i); } else { s->black = color.pixel; } } else { s->black = BlackPixel (dpy, i); } if (prefs.bgstr) { XColor color; if (XAllocNamedColor (dpy, DefaultColormap (dpy, s->num), prefs.bgstr, &color, &color) == 0) { fprintf (stderr, "XAllocNamedColor - allocation of bg color failed.\n"); s->white = WhitePixel (dpy, i); } else { s->white = color.pixel; } } else { s->white = WhitePixel (dpy, i); } #ifdef THREE_D { XColor topcolor; XColor botcolor; XColor get_c; get_c.pixel = s->white; if ((get_c.pixel == WhitePixel (dpy, s->num)) || (get_c.pixel == BlackPixel (dpy, s->num))) { topcolor.red = L_TOP (L_OFF_R); topcolor.green = L_TOP (L_OFF_G); topcolor.blue = L_TOP (L_OFF_B); botcolor.red = L_BOT (L_OFF_R); botcolor.green = L_BOT (L_OFF_G); botcolor.blue = L_BOT (L_OFF_B); } else { XQueryColor (dpy, s->def_cmap, &get_c); topcolor.red = L_TOP (get_c.red); topcolor.green = L_TOP (get_c.green); topcolor.blue = L_TOP (get_c.blue); botcolor.red = L_BOT (get_c.red); botcolor.green = L_BOT (get_c.green); botcolor.blue = L_BOT (get_c.blue); } XAllocColor (dpy, s->def_cmap, &topcolor); XAllocColor (dpy, s->def_cmap, &botcolor); s->topwhite = topcolor.pixel; s->botwhite = botcolor.pixel; gv.foreground = s->topwhite; gv.line_width = 0; mask = GCForeground | GCLineWidth; s->topwhitegc = XCreateGC (dpy, s->root, mask, &gv); gv.foreground = s->botwhite; gv.line_width = 0; mask = GCForeground | GCLineWidth; s->botwhitegc = XCreateGC (dpy, s->root, mask, &gv); get_c.pixel = s->black; if ((get_c.pixel == WhitePixel (dpy, s->num)) || (get_c.pixel == BlackPixel (dpy, s->num))) { topcolor.red = L_TOP (L_ON_R); topcolor.green = L_TOP (L_ON_G); topcolor.blue = L_TOP (L_ON_B); botcolor.red = L_BOT (L_ON_R); botcolor.green = L_BOT (L_ON_G); botcolor.blue = L_BOT (L_ON_B); } else { XQueryColor (dpy, s->def_cmap, &get_c); topcolor.red = L_TOP (get_c.red); topcolor.green = L_TOP (get_c.green); topcolor.blue = L_TOP (get_c.blue); botcolor.red = L_BOT (get_c.red); botcolor.green = L_BOT (get_c.green); botcolor.blue = L_BOT (get_c.blue); } XAllocColor (dpy, s->def_cmap, &topcolor); XAllocColor (dpy, s->def_cmap, &botcolor); s->topblack = topcolor.pixel; s->botblack = botcolor.pixel; gv.foreground = s->topblack; gv.line_width = 0; mask = GCForeground | GCLineWidth; s->topblackgc = XCreateGC (dpy, s->root, mask, &gv); gv.foreground = s->botblack; gv.line_width = 0; mask = GCForeground | GCLineWidth; s->botblackgc = XCreateGC (dpy, s->root, mask, &gv); } #endif gv.foreground = s->black ^ s->white; gv.background = s->white; gv.function = GXxor; gv.line_width = 0; gv.subwindow_mode = IncludeInferiors; mask = GCForeground | GCBackground | GCFunction | GCLineWidth | GCSubwindowMode; if (font != 0) { gv.font = font->fid; mask |= GCFont; } s->gc = XCreateGC (dpy, s->root, mask, &gv); s->place = XCreateFontCursor (dpy, XC_top_left_corner); s->sweep = XCreateFontCursor (dpy, XC_bottom_right_corner); XSelectInput (dpy, s->root, SubstructureRedirectMask | SubstructureNotifyMask | ColormapChangeMask | PropertyChangeMask | ButtonPressMask | ButtonReleaseMask); XSync (dpy, False); /* lars stuff */ s->desktop = 0; for (t = 0; t < prefs.desktops; t++) { s->clickthru[t] = prefs.clickthru[s->num][t]; s->tile_resize[t] = prefs.tile_resize[s->num][t]; s->skip_focus[t] = prefs.skip_focus[s->num][t]; s->left_track_width[t] = prefs.left_track_width[s->num][t]; s->bigmr[t] = 1; s->focused[t] = 0; s->notilefocused[t] = 0; s->notile_raised[t] = 0; } s->barwin = XCreateSimpleWindow (dpy, s->root, BAR_X (s), BAR_Y (s), BAR_WIDTH (s), BAR_HEIGHT, 0, s->black, s->white); XSelectInput (dpy, s->barwin, ExposureMask | ButtonPressMask | ButtonReleaseMask); raise_tbar (s); s->tile_height = BAR_Y (s); s->res_height = BAR_Y (s); } ScreenInfo * getscreen (Window w) { int i; for (i = 0; i < num_screens; i++) if (screens[i].root == w) return &screens[i]; return 0; } void sendcmessage (Window w, Atom a, long x, int isroot) { XEvent ev; long mask; memset (&ev, 0, sizeof (ev)); ev.xclient.type = ClientMessage; ev.xclient.window = w; ev.xclient.message_type = a; ev.xclient.format = 32; ev.xclient.data.l[0] = x; ev.xclient.data.l[1] = CurrentTime; mask = 0L; if (isroot) mask = SubstructureRedirectMask; /* magic! */ XSendEvent (dpy, w, False, mask, &ev); } void sendconfig (Client * c) { XConfigureEvent ce; ce.type = ConfigureNotify; ce.event = c->window; ce.window = c->window; ce.x = c->x; ce.y = c->y; ce.width = c->dx; ce.height = c->dy; ce.border_width = c->border; ce.above = None; ce.override_redirect = 0; XSendEvent (dpy, c->window, False, StructureNotifyMask, (XEvent *) & ce); } void cleanup (void) { Client *c, *cc[2], *next; XWindowChanges wc; int i; /* order of un-reparenting determines final stacking order... */ cc[0] = cc[1] = 0; for (c = clients; c; c = next) { next = c->next; i = normal (c); c->next = cc[i]; cc[i] = c; } for (i = 0; i < 2; i++) { for (c = cc[i]; c; c = c->next) { if (!withdrawn (c)) { gravitate (c, 1); XReparentWindow (dpy, c->window, c->screen->root, c->x, c->y); } wc.border_width = c->border; XConfigureWindow (dpy, c->window, CWBorderWidth, &wc); } } XSetInputFocus (dpy, PointerRoot, RevertToPointerRoot, CurrentTime); for (i = 0; i < num_screens; i++) cmapnofocus (&screens[i]); XCloseDisplay (dpy); } larswm-7.5.3/manage.c0000644000000000000000000002227710065667625014414 0ustar rootroot00000000000000/* Copyright (c) 1994-1996 David Hogan, see README for licence details */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" int manage (Client * c, int mapped) { int dohide, docenter = 1, state; long msize; XClassHint class; XWMHints *hints; XSelectInput (dpy, c->window, ColormapChangeMask | PropertyChangeMask | EnterWindowMask | FocusChangeMask); c->istool = 0; c->issticky = 0; c->isnotile = 0; if (XGetClassHint (dpy, c->window, &class) != 0) { c->instance = class.res_name; c->class = class.res_class; } else { c->instance = 0; c->class = 0; } c->iconname = getprop (c->window, XA_WM_ICON_NAME); c->name = getprop (c->window, XA_WM_NAME); setlabel (c); hints = XGetWMHints (dpy, c->window); if (XGetWMNormalHints (dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0) { c->size.flags = PSize; } if (is_tool (c)) { c->istool = 1; c->isfloat = 1; c->issticky = 1; c->isnotile = 1; } if (is_float (c)) { c->isfloat = 1; c->isnotile = 1; } if (is_sticky (c)) { c->issticky = 1; } if (is_notile (c)) { c->isnotile = 1; } getcmaps (c); getproto (c); gettrans (c); if (c->trans != None) { c->isnotile = 1; } if (!getstate (c->window, &state)) { state = hints ? hints->initial_state : NormalState; } dohide = (state == IconicState); if ((c->size.flags & USPosition) || (c->size.flags & PPosition)) { docenter = 0; } if (c->size.flags & PBaseSize) { c->min_dx = c->size.base_width; c->min_dy = c->size.base_height; } else if (c->size.flags & PMinSize) { c->min_dx = c->size.min_width; c->min_dy = c->size.min_height; } else { c->min_dx = c->min_dy = 1; } if (hints) { XFree (hints); } gravitate (c, 0); c->parent = XCreateSimpleWindow (dpy, c->screen->root, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER), 0, c->screen->black, c->screen->white); XSelectInput (dpy, c->parent, ExposureMask | SubstructureRedirectMask | SubstructureNotifyMask); if (mapped) { c->reparenting = 1; } XSetWindowBorderWidth (dpy, c->window, 0); XReparentWindow (dpy, c->window, c->parent, BORDER, BORDER); c->isshaped = 0; if (shape) { XShapeSelectInput (dpy, c->window, ShapeNotifyMask); setshape (c); } XAddToSaveSet (dpy, c->window); if (dohide) { hide (c); } else { int dt = is_dt (c); if (dt < 0) { dt = c->screen->desktop; } c->desktop = dt; if (c->desktop != c->screen->desktop) { goto_desktop (c->screen, c->desktop); } XMapWindow (dpy, c->window); XMapRaised (dpy, c->parent); top (c); if ((c->trans != None) && current && (current->window == c->trans)) { active (c); } else if ((mouse_on_screen () == c->screen) || (current && current->screen == c->screen)) { active (c); } else { setactive (c, 0); } wmsetstate (c, NormalState); if (docenter) { move_center (c); } } if (current && (current != c)) { cmapfocus (current); } initkeys (c); c->init = 1; return 1; } void scanwins (ScreenInfo * s) { unsigned int i, nwins, dt; Client *c; Window dw1, dw2, *wins; XWindowAttributes attr; XQueryTree (dpy, s->root, &dw1, &dw2, &wins, &nwins); for (i = 0; i < nwins; i++) { XGetWindowAttributes (dpy, wins[i], &attr); if (attr.override_redirect || wins[i] == s->barwin) continue; c = getclient (wins[i], 1); if (c != 0 && c->window == wins[i] && !c->init) { c->x = attr.x; c->y = attr.y; c->dx = attr.width; c->dy = attr.height; c->border = attr.border_width; c->screen = s; c->parent = s->root; if (attr.map_state == IsViewable) manage (c, 1); if ((dt = is_dt (c)) >= 0) { if (dt < prefs.desktops) c->desktop = dt; } if (c->desktop != c->screen->desktop) move_hide (c); } } XFree ((void *) wins); /* cast is to shut stoopid compiler up */ } void gettrans (Client * c) { Window trans; trans = None; if (XGetTransientForHint (dpy, c->window, &trans) != 0) c->trans = trans; else c->trans = None; } void withdraw (Client * c) { XUnmapWindow (dpy, c->parent); gravitate (c, 1); XReparentWindow (dpy, c->window, c->screen->root, c->x, c->y); gravitate (c, 0); XRemoveFromSaveSet (dpy, c->window); wmsetstate (c, WithdrawnState); ignore_badwindow = 1; XSync (dpy, False); ignore_badwindow = 0; } /* This seemed like such a simple concept in theory..... */ void gravitate (Client * c, int invert) { int dx = 0; int dy = 0; int gravity = NorthWestGravity; if (!c) return; if (c->size.flags & PWinGravity) gravity = c->size.win_gravity; switch (gravity) { case NorthEastGravity: case EastGravity: case SouthEastGravity: dx = -BORDER; break; } switch (gravity) { case SouthWestGravity: case SouthGravity: case SouthEastGravity: dy = -BAR_HEIGHT - BORDER; break; } if (invert) { dx = -dx; dy = -dy; } c->x += dx; c->y += dy; } static void installcmap (ScreenInfo * s, Colormap cmap) { if (cmap == None) XInstallColormap (dpy, s->def_cmap); else XInstallColormap (dpy, cmap); } void cmapfocus (Client * c) { int i, found; Client *cc; if (c == 0) return; else if (c->ncmapwins != 0) { found = 0; for (i = c->ncmapwins - 1; i >= 0; i--) { installcmap (c->screen, c->wmcmaps[i]); if (c->cmapwins[i] == c->window) found++; } if (!found) installcmap (c->screen, c->cmap); } else if (c->trans != None && (cc = getclient (c->trans, 0)) != 0 && cc->ncmapwins != 0) cmapfocus (cc); else installcmap (c->screen, c->cmap); } void cmapnofocus (ScreenInfo * s) { installcmap (s, None); } void getcmaps (Client * c) { int n, i; Window *cw; XWindowAttributes attr; if (!c->init) { XGetWindowAttributes (dpy, c->window, &attr); c->cmap = attr.colormap; } n = _getprop (c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **) &cw); if (c->ncmapwins != 0) { XFree ((char *) c->cmapwins); free ((char *) c->wmcmaps); } if (n <= 0) { c->ncmapwins = 0; return; } c->ncmapwins = n; c->cmapwins = cw; c->wmcmaps = (Colormap *) malloc (n * sizeof (Colormap)); for (i = 0; i < n; i++) { if (cw[i] == c->window) c->wmcmaps[i] = c->cmap; else { XSelectInput (dpy, cw[i], ColormapChangeMask); XGetWindowAttributes (dpy, cw[i], &attr); c->wmcmaps[i] = attr.colormap; } } } void setlabel (Client * c) { char *label; if (c->name != 0) label = c->name; else if (c->iconname != 0) label = c->iconname; else if (c->instance != 0) label = c->instance; else if (c->class != 0) label = c->class; else label = "???"; c->label = label; if (normal (c)) draw_border (c, c == current ? 1 : 0); if (c == current) update_tbar (); } void setshape (Client * c) { int n, order; XRectangle *rect; /* don't try to add a border if the window is non-rectangular */ rect = XShapeGetRectangles (dpy, c->window, ShapeBounding, &n, &order); if (n > 1) { XShapeCombineShape (dpy, c->parent, ShapeBounding, BORDER, BORDER, c->window, ShapeBounding, ShapeSet); c->isshaped = 1; } else { c->isshaped = 0; } XFree ((void *) rect); } int _getprop (Window w, Atom a, Atom type, long len, unsigned char **p) { Atom real_type; int format; unsigned long n, extra; int status; status = XGetWindowProperty (dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p); if (status != Success || *p == 0) return -1; if (n == 0) XFree ((void *) *p); /* could check real_type, format, extra here... */ return n; } char * getprop (Window w, Atom a) { unsigned char *p; if (_getprop (w, a, XA_STRING, 100L, &p) <= 0) return 0; return (char *) p; } int get1prop (Window w, Atom a, Atom type) { char **p, *x; if (_getprop (w, a, type, 1L, (unsigned char **) &p) <= 0) return 0; x = *p; XFree ((void *) p); return (int) x; } void wmsetstate (Client * c, int state) { long data[2]; data[0] = (long) state; data[1] = (long) None; c->state = state; XChangeProperty (dpy, c->window, wm_state, wm_state, 32, PropModeReplace, (unsigned char *) data, 2); } int getstate (Window w, int *state) { long *p = 0; if (_getprop (w, wm_state, wm_state, 2L, (unsigned char **) &p) <= 0) return 0; *state = (int) *p; XFree ((char *) p); return 1; } void getproto (Client * c) { Atom *p; int i; long n; Window w; w = c->window; c->proto = 0; if ((n = _getprop (w, wm_protocols, XA_ATOM, 20L, (unsigned char **) &p)) <= 0) return; for (i = 0; i < n; i++) if (p[i] == wm_delete) c->proto |= Pdelete; XFree ((char *) p); } larswm-7.5.3/mouse.c0000644000000000000000000001340710065667625014307 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ /* this is my replacement for the old grab.c */ #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" void adjust_hints (Client * c) { if (c->size.flags & PResizeInc) { c->dx = c->min_dx + (c->dx - c->min_dx) / c->size.width_inc * c->size.width_inc; c->dy = c->min_dy + (c->dy - c->min_dy) / c->size.height_inc * c->size.height_inc; } if (c->size.flags & PMinSize) { if (c->dx < c->size.min_width) c->dx = c->size.min_width; if (c->dy < c->size.min_height) c->dy = c->size.min_height; } if (c->dx < 1) c->dx = 1; if (c->dy < 1) c->dy = 1; if (c->size.flags & PMaxSize) { if (c->dx > c->size.max_width) c->dx = c->size.max_width; if (c->dy > c->size.max_height) c->dy = c->size.max_height; } } void move_opaque (Client * c) { XEvent report; Client *p; int old_x, old_y; int move_x, move_y; char geo[16]; int len; if (!c) return; getmouse (&old_x, &old_y, c->screen); XMapRaised (dpy, c->parent); setmouse (c->x, c->y, c->screen); XChangeActivePointerGrab (dpy, PointerMotionHintMask | ButtonMotionMask | ButtonReleaseMask | OwnerGrabButtonMask, c->screen->place, CurrentTime); while (1) { XNextEvent (dpy, &report); switch (report.type) { #ifdef THREE_D case Expose: p = getclient (report.xexpose.window, 0); if (p) { draw_border (p, p == current ? 1 : 0); } break; #endif case ButtonRelease: if (report.xbutton.button == Button1) { getmouse (&move_x, &move_y, c->screen); c->x = move_x; c->y = move_y; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); setmouse (old_x, old_y, c->screen); update_tbar (); return; } break; case MotionNotify: while (XCheckTypedEvent (dpy, MotionNotify, &report)); getmouse (&move_x, &move_y, c->screen); XMoveWindow (dpy, c->parent, move_x, move_y); sendconfig (c); len = sprintf (geo, "+%d+%d", move_x, move_y); XClearWindow (dpy, c->screen->barwin); #ifdef THREE_D XDrawLine (dpy, c->screen->barwin, c->screen->botwhitegc, 0, BAR_HEIGHT - 1, BAR_WIDTH (c->screen) - 1, BAR_HEIGHT - 1); XDrawLine (dpy, c->screen->barwin, c->screen->botwhitegc, BAR_WIDTH (c->screen) - 1, BAR_HEIGHT - 1, BAR_WIDTH (c->screen) - 1, 0); XDrawLine (dpy, c->screen->barwin, c->screen->topwhitegc, 0, 0, BAR_WIDTH (c->screen) - 1, 0); XDrawLine (dpy, c->screen->barwin, c->screen->topwhitegc, 0, 0, 0, BAR_HEIGHT - 1); #endif XDrawString (dpy, c->screen->barwin, c->screen->gc, BAR_HEIGHT, BAR_TEXT_Y, geo, len); break; } } } void resize_opaque (Client * c) { XEvent report; Client *p; int old_x, old_y; int move_x, move_y; char geo[32]; int len, sx, sy, rx = 0, ry = 0, mx = 0, my = 0; if (!c) return; getmouse (&old_x, &old_y, c->screen); if (c->size.flags & PMinSize) { mx = c->size.min_width; my = c->size.min_height; } if (c->size.flags & PResizeInc) { rx = c->size.width_inc; ry = c->size.height_inc; } XMapRaised (dpy, c->parent); setmouse (c->x + c->dx + 1 + BORDER, c->y + c->dy + 1 + BORDER, c->screen); XChangeActivePointerGrab (dpy, PointerMotionHintMask | ButtonMotionMask | ButtonReleaseMask | OwnerGrabButtonMask, c->screen->sweep, CurrentTime); while (1) { XNextEvent (dpy, &report); switch (report.type) { #ifdef THREE_D case Expose: p = getclient (report.xexpose.window, 0); if (p) { draw_border (p, p == current ? 1 : 0); } break; #endif case ButtonRelease: if (report.xbutton.button == Button1) { getmouse (&move_x, &move_y, c->screen); c->dx = move_x - BORDER - c->x - 1; c->dy = move_y - BORDER - c->y - 1; adjust_hints (c); XResizeWindow (dpy, c->window, c->dx, c->dy); XResizeWindow (dpy, c->parent, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); sendconfig (c); if (shape) setshape (c); setmouse (old_x, old_y, c->screen); update_tbar (); return; } break; case MotionNotify: while (XCheckTypedEvent (dpy, MotionNotify, &report)); getmouse (&move_x, &move_y, c->screen); c->dx = move_x - BORDER - c->x - 1; c->dy = move_y - BORDER - c->y - 1; adjust_hints (c); sx = c->dx; sy = c->dy; XResizeWindow (dpy, c->window, c->dx, c->dy); XResizeWindow (dpy, c->parent, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); sendconfig (c); if (shape) setshape (c); if (rx) { if (mx) sx -= mx; sx /= rx; sx++; } if (ry) { if (my) sy -= my; sy /= ry; sy++; } if (rx || ry) len = sprintf (geo, "%dx%d (%dx%d)", sx, sy, c->dx, c->dy); else len = sprintf (geo, "%dx%d", c->dx, c->dy); XClearWindow (dpy, c->screen->barwin); #ifdef THREE_D XDrawLine (dpy, c->screen->barwin, c->screen->botwhitegc, 0, BAR_HEIGHT - 1, BAR_WIDTH (c->screen) - 1, BAR_HEIGHT - 1); XDrawLine (dpy, c->screen->barwin, c->screen->botwhitegc, BAR_WIDTH (c->screen) - 1, BAR_HEIGHT - 1, BAR_WIDTH (c->screen) - 1, 0); XDrawLine (dpy, c->screen->barwin, c->screen->topwhitegc, 0, 0, BAR_WIDTH (c->screen) - 1, 0); XDrawLine (dpy, c->screen->barwin, c->screen->topwhitegc, 0, 0, 0, BAR_HEIGHT - 1); #endif XDrawString (dpy, c->screen->barwin, c->screen->gc, BAR_HEIGHT, BAR_TEXT_Y, geo, len); break; } } } larswm-7.5.3/prefs.c0000644000000000000000000011021610065667625014272 0ustar rootroot00000000000000/* Copyright (c) 2000 Lars Bernhardsson, see README for licence details */ /* many ideas borrowed from blackbox. */ #include #include #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" #define DEFAULT_MOD (ShiftMask | ControlMask) #define MOVE_MOD (ShiftMask | Mod1Mask) #define CLOSE_MOD (ControlMask | Mod1Mask) #define GROW_MOD (ShiftMask | ControlMask | Mod1Mask) Prefs prefs; void set_defaults (void) { int i, j; memset (&prefs, 0, sizeof (prefs)); for (i = 0; i < MAXSCREENS; i++) { for (j = 0; j < MAXDESKTOPS; j++) { prefs.clickthru[i][j] = 1; prefs.skip_focus[i][j] = 1; prefs.tile_resize[i][j] = 1; prefs.left_track_width[i][j] = 60; } } prefs.desktops = 4; for (i = 0; i < MAXSCREENS; i++) { prefs.dtname[i][0] = "[A---]"; prefs.dtname[i][1] = "[-B--]"; prefs.dtname[i][2] = "[--C-]"; prefs.dtname[i][3] = "[---D]"; prefs.dtname[i][4] = "[E---]"; prefs.dtname[i][5] = "[-F--]"; prefs.dtname[i][6] = "[--G-]"; prefs.dtname[i][7] = "[---H]"; prefs.dtname[i][8] = "[I---]"; prefs.dtname[i][9] = "[-J--]"; prefs.dtname[i][10] = "[--K-]"; prefs.dtname[i][11] = "[---L]"; prefs.dtname[i][12] = "[M---]"; prefs.dtname[i][13] = "[-N--]"; prefs.dtname[i][14] = "[--O-]"; prefs.dtname[i][15] = "[---P]"; } prefs.prev_screen_key = XK_Prior; prefs.prev_screen_mod = DEFAULT_MOD; prefs.next_screen_key = XK_Next; prefs.next_screen_mod = DEFAULT_MOD; prefs.prev_desktop_key = XK_Left; prefs.prev_desktop_mod = DEFAULT_MOD; prefs.prev_desktop_drag_key = XK_Left; prefs.prev_desktop_drag_mod = MOVE_MOD; prefs.next_desktop_key = XK_Right; prefs.next_desktop_mod = DEFAULT_MOD; prefs.next_desktop_drag_key = XK_Right; prefs.next_desktop_drag_mod = MOVE_MOD; prefs.prev_window_key = XK_Up; prefs.prev_window_mod = DEFAULT_MOD; prefs.next_window_key = XK_Down; prefs.next_window_mod = DEFAULT_MOD; prefs.raise_notile_key = XK_BackSpace; prefs.raise_notile_mod = DEFAULT_MOD; prefs.move_northwest_key = XK_KP_Home; prefs.move_northwest_mod = DEFAULT_MOD; prefs.move_north_key = XK_KP_Up; prefs.move_north_mod = DEFAULT_MOD; prefs.move_northeast_key = XK_KP_Prior; prefs.move_northeast_mod = DEFAULT_MOD; prefs.move_west_key = XK_KP_Left; prefs.move_west_mod = DEFAULT_MOD; prefs.move_center_key = XK_KP_Begin; prefs.move_center_mod = DEFAULT_MOD; prefs.move_east_key = XK_KP_Right; prefs.move_east_mod = DEFAULT_MOD; prefs.move_southwest_key = XK_KP_End; prefs.move_southwest_mod = DEFAULT_MOD; prefs.move_south_key = XK_KP_Down; prefs.move_south_mod = DEFAULT_MOD; prefs.move_southeast_key = XK_KP_Next; prefs.move_southeast_mod = DEFAULT_MOD; prefs.move_select_key = XK_space; prefs.move_select_mod = DEFAULT_MOD; prefs.move_aside_key = XK_space; prefs.move_aside_mod = CLOSE_MOD; prefs.move_aside_other_key = XK_0; prefs.move_aside_other_mod = DEFAULT_MOD; prefs.move_sd_key = XK_space; prefs.move_sd_mod = MOVE_MOD; prefs.toggle_inc_key = XK_KP_Insert; prefs.toggle_inc_mod = MOVE_MOD; prefs.move_up_key = XK_KP_Up; prefs.move_up_mod = MOVE_MOD; prefs.move_down_key = XK_KP_Down; prefs.move_down_mod = MOVE_MOD; prefs.move_left_key = XK_KP_Left; prefs.move_left_mod = MOVE_MOD; prefs.move_right_key = XK_KP_Right; prefs.move_right_mod = MOVE_MOD; prefs.grow_vert_key = XK_KP_Up; prefs.grow_vert_mod = GROW_MOD; prefs.shrink_vert_key = XK_KP_Down; prefs.shrink_vert_mod = GROW_MOD; prefs.grow_horiz_key = XK_KP_Right; prefs.grow_horiz_mod = GROW_MOD; prefs.shrink_horiz_key = XK_KP_Left; prefs.shrink_horiz_mod = GROW_MOD; prefs.grow_both_key = XK_KP_Home; prefs.grow_both_mod = GROW_MOD; prefs.shrink_both_key = XK_KP_End; prefs.shrink_both_mod = GROW_MOD; prefs.zoom_vert_key = XK_KP_Home; prefs.zoom_vert_mod = MOVE_MOD; prefs.zoom_horiz_key = XK_KP_End; prefs.zoom_horiz_mod = MOVE_MOD; prefs.zoom_full_key = XK_KP_Begin; prefs.zoom_full_mod = MOVE_MOD; prefs.zoom_full2_key = XK_KP_Begin; prefs.zoom_full2_mod = GROW_MOD; prefs.hide_key = XK_z; prefs.hide_mod = CLOSE_MOD; prefs.unhide_key = XK_x; prefs.unhide_mod = CLOSE_MOD; prefs.close_key = XK_w; prefs.close_mod = CLOSE_MOD; /* provide defaults for up to 12 virtual desktops */ prefs.goto_desktop_key[0] = XK_F1; prefs.goto_desktop_mod[0] = DEFAULT_MOD; prefs.goto_desktop_key[1] = XK_F2; prefs.goto_desktop_mod[1] = DEFAULT_MOD; prefs.goto_desktop_key[2] = XK_F3; prefs.goto_desktop_mod[2] = DEFAULT_MOD; prefs.goto_desktop_key[3] = XK_F4; prefs.goto_desktop_mod[3] = DEFAULT_MOD; prefs.goto_desktop_key[4] = XK_F5; prefs.goto_desktop_mod[4] = DEFAULT_MOD; prefs.goto_desktop_key[5] = XK_F6; prefs.goto_desktop_mod[5] = DEFAULT_MOD; prefs.goto_desktop_key[6] = XK_F7; prefs.goto_desktop_mod[6] = DEFAULT_MOD; prefs.goto_desktop_key[7] = XK_F8; prefs.goto_desktop_mod[7] = DEFAULT_MOD; prefs.goto_desktop_key[8] = XK_F9; prefs.goto_desktop_mod[8] = DEFAULT_MOD; prefs.goto_desktop_key[9] = XK_F10; prefs.goto_desktop_mod[9] = DEFAULT_MOD; prefs.goto_desktop_key[10] = XK_F11; prefs.goto_desktop_mod[10] = DEFAULT_MOD; prefs.goto_desktop_key[11] = XK_F12; prefs.goto_desktop_mod[11] = DEFAULT_MOD; } char * show_bool (int x) { if (x) return "True"; else return "False"; } char * show_mod (unsigned long mod) { static char r[48]; r[0] = '\0'; if (!mod) { return "None"; } if (mod & ShiftMask) { strcat (r, "Shift"); } if (mod & LockMask) { if (r[0]) strcat (r, "+"); strcat (r, "Lock"); } if (mod & ControlMask) { if (r[0]) strcat (r, "+"); strcat (r, "Control"); } if (mod & Mod1Mask) { if (r[0]) strcat (r, "+"); strcat (r, "Alt"); } if (mod & Mod2Mask) { if (r[0]) strcat (r, "+"); strcat (r, "Mod2"); } if (mod & Mod3Mask) { if (r[0]) strcat (r, "+"); strcat (r, "Mod3"); } if (mod & Mod4Mask) { if (r[0]) strcat (r, "+"); strcat (r, "Mod4"); } if (mod & Mod5Mask) { if (r[0]) strcat (r, "+"); strcat (r, "Mod5"); } return r; } void dump_prefs (void) { printf ("!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf ("! larswm configuration !\n"); printf ("!!!!!!!!!!!!!!!!!!!!!!!!\n"); printf ("!\n"); printf ("! Version: %s\n", VERSION); printf ("!\n"); printf ("! If you edit this, do not forget to uncomment any lines that you change.\n"); printf ("!\n"); printf ("!\n"); printf ("! Status bar and window border colors:\n"); printf ("!\n"); if (prefs.fgstr) printf ("! larswm.foreground: %s\n", prefs.fgstr); else printf ("! larswm.foreground: black\n"); if (prefs.bgstr) printf ("! larswm.background: %s\n", prefs.bgstr); else printf ("! larswm.background: white\n"); printf ("!\n"); printf ("! Status bar font:\n"); printf ("!\n"); if (prefs.fname) printf ("! larswm.font: %s\n", prefs.fname); else printf ("! larswm.font: fixed\n"); printf ("!\n"); printf ("! Number of virtual desktops per physical screen: (1 - %d)\n", MAXDESKTOPS); printf ("!\n"); printf ("! larswm.desktops: %d\n", prefs.desktops); printf ("!\n"); printf ("! Virtual desktop names:\n"); printf ("!\n"); printf ("! larswm.?.0.dtname: %s\n", prefs.dtname[0][0]); printf ("! larswm.?.1.dtname: %s\n", prefs.dtname[0][1]); printf ("! larswm.?.2.dtname: %s\n", prefs.dtname[0][2]); printf ("! larswm.?.3.dtname: %s\n", prefs.dtname[0][3]); printf ("!\n"); printf ("! Resize windows when tiling? (If not, move to and stack in right track)\n"); printf ("!\n"); printf ("! larswm.?.?.tile_resize: %s\n", show_bool (prefs.tile_resize[0][0])); printf ("!\n"); printf ("! Width of left track in percent: (5-95)\n"); printf ("!\n"); printf ("! larswm.?.?.left_track_width: %d\n", prefs.left_track_width[0][0]); printf ("!\n"); printf ("! Don't retile on focus change?\n"); printf ("!\n"); printf ("! larswm.?.?.skip_focus: %s\n", show_bool (prefs.skip_focus[0][0])); printf ("!\n"); printf ("! When clicking to focus, also pass click on to client?\n"); printf ("!\n"); printf ("! larswm.?.?.clickthru: %s\n", show_bool (prefs.clickthru[0][0])); printf ("!\n"); printf ("! Application commands for shortcuts:\n"); printf ("! Add one line for each application. Must have different numbers between 0 and %d.\n", MAXAPPS - 1); printf ("!\n"); printf ("! larswm.application.0: command\n"); printf ("!\n"); printf ("! Application commands for mouse clicks:\n"); printf ("!\n"); printf ("! larswm.button1.application: command\n"); printf ("! larswm.button2.application: command\n"); printf ("! larswm.button3.application: command\n"); printf ("!\n"); printf ("! * In all the class lists, the Instance is optional *\n"); printf ("!\n"); printf ("! Tool applications: (Will NOT be tiled, will be tiled around and will be sticky)\n"); printf ("! Add one line for each class. Must have different numbers between 0 and %d.\n", MAXTOOLCLASS - 1); printf ("!\n"); printf ("! larswm.toolclass.0: Class~Instance\n"); printf ("!\n"); printf ("! Floating applications: (Will always stay on top of other applications)\n"); printf ("! Add one line for each class. Must have different numbers between 0 and %d.\n", MAXFLOATCLASS - 1); printf ("!\n"); printf ("! larswm.floatclass.0: Class~Instance\n"); printf ("!\n"); printf ("! Sticky applications: (Will be visible on all virtual desktops)\n"); printf ("! Add one line for each class. Must have different numbers between 0 and %d.\n", MAXSTICKYCLASS - 1); printf ("!\n"); printf ("! larswm.stickyclass.0: Class~Instance\n"); printf ("!\n"); printf ("! Applications to include in tiling: (Will be put in the tiled subdesktop)\n"); printf ("! Add one line for each class. Must have different numbers between 0 and %d.\n", MAXNOTILECLASS - 1); printf ("!\n"); printf ("! larswm.dotileclass.0: Class~Instance\n"); printf ("!\n"); printf ("! Associate a window class with a desktop number:\n"); printf ("! Must provide both class and desktop number.\n"); printf ("!\n"); printf ("! larswm.dtclass.0: Class~Instance\n"); printf ("! larswm.dtnum.0: 0\n"); printf ("!\n"); printf ("! Key bindings: (Modifiers: Shift, Lock, Control, Mod1 or Alt, Mod2, Mod3, Mod4 and Mod5)\n"); printf ("!\n"); printf ("! larswm.prev_screen_key: %s\n", XKeysymToString (prefs.prev_screen_key)); printf ("! larswm.prev_screen_mod: %s\n", show_mod (prefs.prev_screen_mod)); printf ("!\n"); printf ("! larswm.next_screen_key: %s\n", XKeysymToString (prefs.next_screen_key)); printf ("! larswm.next_screen_mod: %s\n", show_mod (prefs.next_screen_mod)); printf ("!\n"); printf ("! larswm.prev_desktop_key: %s\n", XKeysymToString (prefs.prev_desktop_key)); printf ("! larswm.prev_desktop_mod: %s\n", show_mod (prefs.prev_desktop_mod)); printf ("!\n"); printf ("! larswm.next_desktop_key: %s\n", XKeysymToString (prefs.next_desktop_key)); printf ("! larswm.next_desktop_mod: %s\n", show_mod (prefs.next_desktop_mod)); printf ("!\n"); printf ("! larswm.prev_desktop_drag_key: %s\n", XKeysymToString (prefs.prev_desktop_drag_key)); printf ("! larswm.prev_desktop_drag_mod: %s\n", show_mod (prefs.prev_desktop_drag_mod)); printf ("!\n"); printf ("! larswm.next_desktop_drag_key: %s\n", XKeysymToString (prefs.next_desktop_drag_key)); printf ("! larswm.next_desktop_drag_mod: %s\n", show_mod (prefs.next_desktop_drag_mod)); printf ("!\n"); printf ("! larswm.prev_window_key: %s\n", XKeysymToString (prefs.prev_window_key)); printf ("! larswm.prev_window_mod: %s\n", show_mod (prefs.prev_window_mod)); printf ("!\n"); printf ("! larswm.next_window_key: %s\n", XKeysymToString (prefs.next_window_key)); printf ("! larswm.next_window_mod: %s\n", show_mod (prefs.next_window_mod)); printf ("!\n"); printf ("! larswm.raise_notile_key: %s\n", XKeysymToString (prefs.raise_notile_key)); printf ("! larswm.raise_notile_mod: %s\n", show_mod (prefs.raise_notile_mod)); printf ("!\n"); printf ("! larswm.move_northwest_key: %s\n", XKeysymToString (prefs.move_northwest_key)); printf ("! larswm.move_northwest_mod: %s\n", show_mod (prefs.move_northwest_mod)); printf ("!\n"); printf ("! larswm.move_north_key: %s\n", XKeysymToString (prefs.move_north_key)); printf ("! larswm.move_north_mod: %s\n", show_mod (prefs.move_north_mod)); printf ("!\n"); printf ("! larswm.move_northeast_key: %s\n", XKeysymToString (prefs.move_northeast_key)); printf ("! larswm.move_northeast_mod: %s\n", show_mod (prefs.move_northeast_mod)); printf ("!\n"); printf ("! larswm.move_west_key: %s\n", XKeysymToString (prefs.move_west_key)); printf ("! larswm.move_west_mod: %s\n", show_mod (prefs.move_west_mod)); printf ("!\n"); printf ("! larswm.move_center_key: %s\n", XKeysymToString (prefs.move_center_key)); printf ("! larswm.move_center_mod: %s\n", show_mod (prefs.move_center_mod)); printf ("!\n"); printf ("! larswm.move_east_key: %s\n", XKeysymToString (prefs.move_east_key)); printf ("! larswm.move_east_mod: %s\n", show_mod (prefs.move_east_mod)); printf ("!\n"); printf ("! larswm.move_southwest_key: %s\n", XKeysymToString (prefs.move_southwest_key)); printf ("! larswm.move_southwest_mod: %s\n", show_mod (prefs.move_southwest_mod)); printf ("!\n"); printf ("! larswm.move_south_key: %s\n", XKeysymToString (prefs.move_south_key)); printf ("! larswm.move_south_mod: %s\n", show_mod (prefs.move_south_mod)); printf ("!\n"); printf ("! larswm.move_southeast_key: %s\n", XKeysymToString (prefs.move_southeast_key)); printf ("! larswm.move_southeast_mod: %s\n", show_mod (prefs.move_southeast_mod)); printf ("!\n"); printf ("! larswm.toggle_inc_key: %s\n", XKeysymToString (prefs.toggle_inc_key)); printf ("! larswm.toggle_inc_mod: %s\n", show_mod (prefs.toggle_inc_mod)); printf ("!\n"); printf ("! larswm.move_up_key: %s\n", XKeysymToString (prefs.move_up_key)); printf ("! larswm.move_up_mod: %s\n", show_mod (prefs.move_up_mod)); printf ("!\n"); printf ("! larswm.move_down_key: %s\n", XKeysymToString (prefs.move_down_key)); printf ("! larswm.move_down_mod: %s\n", show_mod (prefs.move_down_mod)); printf ("!\n"); printf ("! larswm.move_left_key: %s\n", XKeysymToString (prefs.move_left_key)); printf ("! larswm.move_left_mod: %s\n", show_mod (prefs.move_left_mod)); printf ("!\n"); printf ("! larswm.move_right_key: %s\n", XKeysymToString (prefs.move_right_key)); printf ("! larswm.move_right_mod: %s\n", show_mod (prefs.move_right_mod)); printf ("!\n"); printf ("! larswm.move_select_key: %s\n", XKeysymToString (prefs.move_select_key)); printf ("! larswm.move_select_mod: %s\n", show_mod (prefs.move_select_mod)); printf ("!\n"); printf ("! larswm.move_aside_key: %s\n", XKeysymToString (prefs.move_aside_key)); printf ("! larswm.move_aside_mod: %s\n", show_mod (prefs.move_aside_mod)); printf ("!\n"); printf ("! larswm.move_aside_other_key: %s\n", XKeysymToString (prefs.move_aside_other_key)); printf ("! larswm.move_aside_other_mod: %s\n", show_mod (prefs.move_aside_other_mod)); printf ("!\n"); printf ("! larswm.move_sd_key: %s\n", XKeysymToString (prefs.move_sd_key)); printf ("! larswm.move_sd_mod: %s\n", show_mod (prefs.move_sd_mod)); printf ("!\n"); printf ("! larswm.grow_vert_key: %s\n", XKeysymToString (prefs.grow_vert_key)); printf ("! larswm.grow_vert_mod: %s\n", show_mod (prefs.grow_vert_mod)); printf ("!\n"); printf ("! larswm.shrink_vert_key: %s\n", XKeysymToString (prefs.shrink_vert_key)); printf ("! larswm.shrink_vert_mod: %s\n", show_mod (prefs.shrink_vert_mod)); printf ("!\n"); printf ("! larswm.grow_horiz_key: %s\n", XKeysymToString (prefs.grow_horiz_key)); printf ("! larswm.grow_horiz_mod: %s\n", show_mod (prefs.grow_horiz_mod)); printf ("!\n"); printf ("! larswm.shrink_horiz_key: %s\n", XKeysymToString (prefs.shrink_horiz_key)); printf ("! larswm.shrink_horiz_mod: %s\n", show_mod (prefs.shrink_horiz_mod)); printf ("!\n"); printf ("! larswm.grow_both_key: %s\n", XKeysymToString (prefs.grow_both_key)); printf ("! larswm.grow_both_mod: %s\n", show_mod (prefs.grow_both_mod)); printf ("!\n"); printf ("! larswm.shrink_both_key: %s\n", XKeysymToString (prefs.shrink_both_key)); printf ("! larswm.shrink_both_mod: %s\n", show_mod (prefs.shrink_both_mod)); printf ("!\n"); printf ("! larswm.zoom_vert_key: %s\n", XKeysymToString (prefs.zoom_vert_key)); printf ("! larswm.zoom_vert_mod: %s\n", show_mod (prefs.zoom_vert_mod)); printf ("!\n"); printf ("! larswm.zoom_horiz_key: %s\n", XKeysymToString (prefs.zoom_horiz_key)); printf ("! larswm.zoom_horiz_mod: %s\n", show_mod (prefs.zoom_horiz_mod)); printf ("!\n"); printf ("! larswm.zoom_full_key: %s\n", XKeysymToString (prefs.zoom_full_key)); printf ("! larswm.zoom_full_mod: %s\n", show_mod (prefs.zoom_full_mod)); printf ("!\n"); printf ("! larswm.zoom_full2_key: %s\n", XKeysymToString (prefs.zoom_full2_key)); printf ("! larswm.zoom_full2_mod: %s\n", show_mod (prefs.zoom_full2_mod)); printf ("!\n"); printf ("! larswm.hide_key: %s\n", XKeysymToString (prefs.hide_key)); printf ("! larswm.hide_mod: %s\n", show_mod (prefs.hide_mod)); printf ("!\n"); printf ("! larswm.unhide_key: %s\n", XKeysymToString (prefs.unhide_key)); printf ("! larswm.unhide_mod: %s\n", show_mod (prefs.unhide_mod)); printf ("!\n"); printf ("! larswm.close_key: %s\n", XKeysymToString (prefs.close_key)); printf ("! larswm.close_mod: %s\n", show_mod (prefs.close_mod)); printf ("!\n"); printf ("! Desktop shortcuts: Defaults are provided for the first 12 desktops, F1-F12.\n"); printf ("! If you have more than 12 desktops, you will have to add key bindings for them\n"); printf ("! or just use prev/next desktop to get to where you want.\n"); printf ("!\n"); printf ("! larswm.goto_desktop_key.0: %s\n", XKeysymToString (prefs.goto_desktop_key[0])); printf ("! larswm.goto_desktop_mod.0: %s\n", show_mod (prefs.goto_desktop_mod[0])); printf ("!\n"); printf ("! Application shortcuts:\n"); printf ("! Use this to add keyboard shortcuts for the larswm.application[] entries.\n"); printf ("!\n"); printf ("! larswm.application_key.0: KeySym\n"); printf ("! larswm.application_mod.0: Modifier\n"); printf ("!\n"); printf ("! End of larswm configuration.\n"); } unsigned long get_mod (char *s) { unsigned long m = 0; if (strstr (s, "shift") || strstr (s, "Shift")) m |= ShiftMask; if (strstr (s, "lock") || strstr (s, "Lock")) m |= LockMask; if (strstr (s, "control") || strstr (s, "Control")) m |= ControlMask; if (strstr (s, "alt") || strstr (s, "Alt")) m |= Mod1Mask; if (strstr (s, "mod1") || strstr (s, "Mod1")) m |= Mod1Mask; if (strstr (s, "mod2") || strstr (s, "Mod2")) m |= Mod2Mask; if (strstr (s, "mod3") || strstr (s, "Mod3")) m |= Mod3Mask; if (strstr (s, "mod4") || strstr (s, "Mod4")) m |= Mod4Mask; if (strstr (s, "mod5") || strstr (s, "Mod5")) m |= Mod5Mask; return m; } int get_bool (const char *s) { if (strcasecmp ("true", s) == 0) return 1; else return 0; } void validate_prefs (void) { int i, j; if (prefs.desktops < 1) prefs.desktops = 1; if (prefs.desktops > MAXDESKTOPS) prefs.desktops = MAXDESKTOPS; for (i = 0; i < MAXSCREENS; i++) { for (j = 0; j < MAXDESKTOPS; j++) { if (prefs.left_track_width[i][j] < 5) prefs.left_track_width[i][j] = 5; if (prefs.left_track_width[i][j] > 95) prefs.left_track_width[i][j] = 95; } } } void check_idx_intfunc (XrmDatabase db, char *r, char *c, int s, int d, int *p, int (*func) (const char *)) { XrmValue v; char *vt; char res[32], cla[32]; sprintf (res, "larswm.%d.%d.%s", s, d, r); sprintf (cla, "Larswm.%d.%d.%s", s, d, c); if (XrmGetResource (db, res, cla, &vt, &v)) *p = func (v.addr); } void check_idx_strfunc (XrmDatabase db, char *r, char *c, int s, int d, char **p, char *(*func) (const char *)) { XrmValue v; char *vt; char res[32], cla[32]; sprintf (res, "larswm.%d.%d.%s", s, d, r); sprintf (cla, "Larswm.%d.%d.%s", s, d, c); if (XrmGetResource (db, res, cla, &vt, &v)) *p = func (v.addr); } void load_prefs (char *filename) { XrmDatabase db = (XrmDatabase) 0; XrmValue v; char *vt; int i, j; set_defaults (); if ((db = XrmGetFileDatabase (filename)) == NULL) if ((db = XrmGetFileDatabase (DEFRC)) == NULL) return; if (XrmGetResource (db, "larswm.desktops", "Larswm.Desktops", &vt, &v)) prefs.desktops = atoi (v.addr); for (i = 0; i < MAXSCREENS; i++) { for (j = 0; j < MAXDESKTOPS; j++) { check_idx_strfunc (db, "dtname", "Dtname", i, j, &prefs.dtname[i][j], strdup); check_idx_intfunc (db, "clickthru", "Clickthru", i, j, &prefs.clickthru[i][j], get_bool); check_idx_intfunc (db, "skip_focus", "Skip_focus", i, j, &prefs.skip_focus[i][j], get_bool); check_idx_intfunc (db, "tile_resize", "Tile_resize", i, j, &prefs.tile_resize[i][j], get_bool); check_idx_intfunc (db, "left_track_width", "Left_track_width", i, j, &prefs.left_track_width[i][j], atoi); } } if (XrmGetResource (db, "larswm.background", "Larswm.Background", &vt, &v)) prefs.bgstr = strdup (v.addr); if (XrmGetResource (db, "larswm.foreground", "Larswm.Foreground", &vt, &v)) prefs.fgstr = strdup (v.addr); if (XrmGetResource (db, "larswm.font", "Larswm.Font", &vt, &v)) prefs.fname = strdup (v.addr); for (i = 0; i < MAXAPPS; i++) { char res[32], cla[32]; sprintf (res, "larswm.application.%d", i); sprintf (cla, "Larswm.Application.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.application[i] = strdup (v.addr); } for (i = 0; i < MAXTOOLCLASS; i++) { char res[32], cla[32]; sprintf (res, "larswm.toolclass.%d", i); sprintf (cla, "Larswm.Toolclass.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.toolclass[i] = strdup (v.addr); } for (i = 0; i < MAXFLOATCLASS; i++) { char res[32], cla[32]; sprintf (res, "larswm.floatclass.%d", i); sprintf (cla, "Larswm.Floatclass.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.floatclass[i] = strdup (v.addr); } for (i = 0; i < MAXSTICKYCLASS; i++) { char res[32], cla[32]; sprintf (res, "larswm.stickyclass.%d", i); sprintf (cla, "Larswm.Stickyclass.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.stickyclass[i] = strdup (v.addr); } for (i = 0; i < MAXNOTILECLASS; i++) { char res[32], cla[32]; sprintf (res, "larswm.dotileclass.%d", i); sprintf (cla, "Larswm.Dotileclass.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.notileclass[i] = strdup (v.addr); } for (i = 0; i < MAXDTCLASS; i++) { char *ts = 0; int dt = -1; char res[32], cla[32]; sprintf (res, "larswm.dtclass.%d", i); sprintf (cla, "Larswm.Dtclass.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) { ts = strdup (v.addr); } sprintf (res, "larswm.dtnum.%d", i); sprintf (cla, "Larswm.Dtnum.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) { dt = atoi (v.addr); } if (ts && (dt > -1) && (dt < prefs.desktops) && (dt < MAXDESKTOPS)) { prefs.dtclass[i] = ts; prefs.dtnum[i] = dt; } } if (XrmGetResource (db, "larswm.prev_screen_key", "Larswm.Prev_screen_key", &vt, &v)) prefs.prev_screen_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.prev_screen_mod", "Larswm.Prev_screen_mod", &vt, &v)) prefs.prev_screen_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.next_screen_key", "Larswm.Next_screen_key", &vt, &v)) prefs.next_screen_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.next_screen_mod", "Larswm.Next_screen_mod", &vt, &v)) prefs.next_screen_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.prev_desktop_key", "Larswm.Prev_desktop_key", &vt, &v)) prefs.prev_desktop_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.prev_desktop_mod", "Larswm.Prev_desktop_mod", &vt, &v)) prefs.prev_desktop_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.prev_desktop_drag_key", "Larswm.Prev_desktop_drag_key", &vt, &v)) prefs.prev_desktop_drag_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.prev_desktop_drag_mod", "Larswm.Prev_desktop_drag_mod", &vt, &v)) prefs.prev_desktop_drag_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.next_desktop_key", "Larswm.Next_desktop_key", &vt, &v)) prefs.next_desktop_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.next_desktop_mod", "Larswm.Next_desktop_mod", &vt, &v)) prefs.next_desktop_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.next_desktop_drag_key", "Larswm.Next_desktop_drag_key", &vt, &v)) prefs.next_desktop_drag_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.next_desktop_drag_mod", "Larswm.Next_desktop_drag_mod", &vt, &v)) prefs.next_desktop_drag_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.prev_window_key", "Larswm.Prev_window_key", &vt, &v)) prefs.prev_window_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.prev_window_mod", "Larswm.Prev_window_mod", &vt, &v)) prefs.prev_window_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.next_window_key", "Larswm.Next_window_key", &vt, &v)) prefs.next_window_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.next_window_mod", "Larswm.Next_window_mod", &vt, &v)) prefs.next_window_mod = get_mod (v.addr); for (i = 0; i < MAXDESKTOPS; i++) { char res[32], cla[32]; sprintf (res, "larswm.goto_desktop_key.%d", i); sprintf (cla, "Larswm.Goto_desktop_key.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.goto_desktop_key[i] = XStringToKeysym (v.addr); sprintf (res, "larswm.goto_desktop_mod.%d", i); sprintf (cla, "Larswm.Goto_desktop_mod.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.goto_desktop_mod[i] = get_mod (v.addr); } for (i = 0; i < MAXBTNAPPS; i++) { char res[32], cla[32]; sprintf (res, "larswm.button%d.application", i + 1); sprintf (cla, "Larswm.Button%d.Application", i + 1); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.btnapplication[i] = strdup (v.addr); } for (i = 0; i < MAXAPPS; i++) { char res[32], cla[32]; sprintf (res, "larswm.application_key.%d", i); sprintf (cla, "Larswm.Application_key.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.application_key[i] = XStringToKeysym (v.addr); sprintf (res, "larswm.application_mod.%d", i); sprintf (cla, "Larswm.Application_mod.%d", i); if (XrmGetResource (db, res, cla, &vt, &v)) prefs.application_mod[i] = get_mod (v.addr); } if (XrmGetResource (db, "larswm.raise_notile_key", "Larswm.Raise_notile_key", &vt, &v)) prefs.raise_notile_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.raise_notile_mod", "Larswm.Raise_notile_mod", &vt, &v)) prefs.raise_notile_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_northwest_key", "Larswm.Move_northwest_key", &vt, &v)) prefs.move_northwest_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_northwest_mod", "Larswm.Move_northwest_mod", &vt, &v)) prefs.move_northwest_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_north_key", "Larswm.Move_north_key", &vt, &v)) prefs.move_north_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_north_mod", "Larswm.Move_north_mod", &vt, &v)) prefs.move_north_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_northeast_key", "Larswm.Move_northeast_key", &vt, &v)) prefs.move_northeast_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_northeast_mod", "Larswm.Move_northeast_mod", &vt, &v)) prefs.move_northeast_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_west_key", "Larswm.Move_west_key", &vt, &v)) prefs.move_west_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_west_mod", "Larswm.Move_west_mod", &vt, &v)) prefs.move_west_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_center_key", "Larswm.Move_center_key", &vt, &v)) prefs.move_center_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_center_mod", "Larswm.Move_center_mod", &vt, &v)) prefs.move_center_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_east_key", "Larswm.Move_east_key", &vt, &v)) prefs.move_east_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_east_mod", "Larswm.Move_east_mod", &vt, &v)) prefs.move_east_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_southwest_key", "Larswm.Move_southwest_key", &vt, &v)) prefs.move_southwest_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_southwest_mod", "Larswm.Move_southwest_mod", &vt, &v)) prefs.move_southwest_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_south_key", "Larswm.Move_south_key", &vt, &v)) prefs.move_south_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_south_mod", "Larswm.Move_south_mod", &vt, &v)) prefs.move_south_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_southeast_key", "Larswm.Move_southeast_key", &vt, &v)) prefs.move_southeast_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_southeast_mod", "Larswm.Move_southeast_mod", &vt, &v)) prefs.move_southeast_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.toggle_inc_key", "Larswm.Toggle_inc_key", &vt, &v)) prefs.toggle_inc_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.toggle_inc_mod", "Larswm.Toggle_inc_mod", &vt, &v)) prefs.toggle_inc_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_up_key", "Larswm.Move_up_key", &vt, &v)) prefs.move_up_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_up_mod", "Larswm.Move_up_mod", &vt, &v)) prefs.move_up_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_down_key", "Larswm.Move_down_key", &vt, &v)) prefs.move_down_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_down_mod", "Larswm.Move_down_mod", &vt, &v)) prefs.move_down_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_left_key", "Larswm.Move_left_key", &vt, &v)) prefs.move_left_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_left_mod", "Larswm.Move_left_mod", &vt, &v)) prefs.move_left_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_right_key", "Larswm.Move_right_key", &vt, &v)) prefs.move_right_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_right_mod", "Larswm.Move_right_mod", &vt, &v)) prefs.move_right_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_select_key", "Larswm.Move_select_key", &vt, &v)) prefs.move_select_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_select_mod", "Larswm.Move_select_mod", &vt, &v)) prefs.move_select_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_aside_key", "Larswm.Move_aside_key", &vt, &v)) prefs.move_aside_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_aside_mod", "Larswm.Move_aside_mod", &vt, &v)) prefs.move_aside_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_aside_other_key", "Larswm.Move_aside_other_key", &vt, &v)) prefs.move_aside_other_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_aside_other_mod", "Larswm.Move_aside_other_mod", &vt, &v)) prefs.move_aside_other_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.move_sd_key", "Larswm.Move_sd_key", &vt, &v)) prefs.move_sd_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.move_sd_mod", "Larswm.Move_sd_mod", &vt, &v)) prefs.move_sd_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.grow_vert_key", "Larswm.Grow_vert_key", &vt, &v)) prefs.grow_vert_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.grow_vert_mod", "Larswm.Grow_vert_mod", &vt, &v)) prefs.grow_vert_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.shrink_vert_key", "Larswm.Shrink_vert_key", &vt, &v)) prefs.shrink_vert_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.shrink_vert_mod", "Larswm.Shrink_vert_mod", &vt, &v)) prefs.shrink_vert_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.grow_horiz_key", "Larswm.Grow_horiz_key", &vt, &v)) prefs.grow_horiz_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.grow_horiz_mod", "Larswm.Grow_horiz_mod", &vt, &v)) prefs.grow_horiz_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.shrink_horiz_key", "Larswm.Shrink_horiz_key", &vt, &v)) prefs.shrink_horiz_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.shrink_horiz_mod", "Larswm.Shrink_horiz_mod", &vt, &v)) prefs.shrink_horiz_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.grow_both_key", "Larswm.Grow_both_key", &vt, &v)) prefs.grow_both_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.grow_both_mod", "Larswm.Grow_both_mod", &vt, &v)) prefs.grow_both_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.shrink_both_key", "Larswm.Shrink_both_key", &vt, &v)) prefs.shrink_both_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.shrink_both_mod", "Larswm.Shrink_both_mod", &vt, &v)) prefs.shrink_both_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.zoom_vert_key", "Larswm.Zoom_vert_key", &vt, &v)) prefs.zoom_vert_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.zoom_vert_mod", "Larswm.Zoom_vert_mod", &vt, &v)) prefs.zoom_vert_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.zoom_horiz_key", "Larswm.Zoom_horiz_key", &vt, &v)) prefs.zoom_horiz_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.zoom_horiz_mod", "Larswm.Zoom_horiz_mod", &vt, &v)) prefs.zoom_horiz_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.zoom_full_key", "Larswm.Zoom_full_key", &vt, &v)) prefs.zoom_full_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.zoom_full_mod", "Larswm.Zoom_full_mod", &vt, &v)) prefs.zoom_full_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.zoom_full2_key", "Larswm.Zoom_full2_key", &vt, &v)) prefs.zoom_full2_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.zoom_full2_mod", "Larswm.Zoom_full2_mod", &vt, &v)) prefs.zoom_full2_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.hide_key", "Larswm.Hide_key", &vt, &v)) prefs.hide_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.hide_mod", "Larswm.Hide_mod", &vt, &v)) prefs.hide_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.unhide_key", "Larswm.Unhide_key", &vt, &v)) prefs.unhide_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.unhide_mod", "Larswm.Unhide_mod", &vt, &v)) prefs.unhide_mod = get_mod (v.addr); if (XrmGetResource (db, "larswm.close_key", "Larswm.Close_key", &vt, &v)) prefs.close_key = XStringToKeysym (v.addr); if (XrmGetResource (db, "larswm.close_mod", "Larswm.Close_mod", &vt, &v)) prefs.close_mod = get_mod (v.addr); validate_prefs (); } larswm-7.5.3/README0000644000000000000000000000675110065667625013677 0ustar rootroot00000000000000*************************************** * larswm - Lars Tiling Window Manager * *************************************** Introduction: -------------------------------------------------------------------------- | | This is not really a completely new window manager, but rather a | heavily modified version of David Hogan's 9wm. | In following his licensing terms, I release this under | a different name than 9wm. | Please see the file README.9wm for David's original license. | | The same deal applies to Arnold Robbins' menu program (9menu) | that is included in the larswm distribution. I changed the name | of it because I made a couple of changes to the code, and also | so that if you use a package manager to install both larswm | and 9menu, you would not get a conflict. | Please see the file README.9menu for Arnold's original license. | -------------------------------------------------------------------------- Where can I find new versions? Where can I find more documentation? http://larswm.fnurt.net How do I compile and install it? xmkmf -a make install install.man Compiling with gcc under Solaris: I don't have Sun C installed, only gcc. In order to make the Imakefile work with the standard X11 installation in /usr/openwin, I had to add a few lines at the top of the Imakefile. If you're having trouble compiling on Solaris, try editing/removing those. ########################################################################## ########################################################################## Known problems: When opening xterms they sometimes think they are 80x24 even though they have been tiled to some other size. Workaround: Put this line in your .bashrc or .cshrc eval `resize` Other issues: 1. Keyboard shortcuts don't work when any of the locked modifiers are active. That is, if you configure a shortcut as Control-Alt-x, then it will not work if ShiftLock, NumLock or ScrollLock is on. Workaround: If you most of the time have NumLock on, you can configure all your keyboard shortcuts to include the Mod2 modifer. That is, if you want to use Alt-Tab to go to previous window, instead of larswm.prev_window_key: Tab larswm.prev_window_mod: Alt change the last line to read larswm.prev_window_mod: Mod2+Alt Now it won't work when NumLock is off, so only do this if NumLock is on most of the time. The names for the modifers you might want to do this for are: Key Symbol ------------------------- CapsLock ShiftLock NumLock Mod2 ScrollLock Mod5 ########################################################################## ########################################################################## SUN KEYBOARD SPECIFICS: To make the KP_ bindings work on a Sun keyboard, I use this xmodmap file: ---BEGIN--- keycode 75 = KP_Home keycode 76 = KP_Up keycode 77 = KP_Prior keycode 98 = KP_Left keycode 99 = KP_Begin keycode 100 = KP_Right keycode 119 = KP_End keycode 120 = KP_Down keycode 121 = KP_Next ---END--- Just put this in a file somewhere, and load it from your .xsession BEFORE starting larswm: ---BEGIN--- xmodmap /path/to/file ---END--- If you are using another type of keyboard, and the keypad doesn't seem to work, use 'xev' to find the keycodes for each key, and then remap them in a similar way. LICENSING: Please see README.9wm for David Hogan's original 9wm license and README.9menu for Arnold Robbins' original 9menu license. The same type of license applies to all of my code. --- Lars Bernhardsson larswm-7.5.3/README.9menu0000644000000000000000000000261510065667625014726 0ustar rootroot00000000000000Sun Jun 15 10:21:08 IDT 2003 This is 9menu, a simple program that allows you to create X menus from the shell, where each menu item will run a command. 9menu is intended for use with 9wm, but can be used with any other window manager. The idea of a command line menu generator is from xmenu, but xmenu was exclusively a pop-up menu, not what I wanted. The files are: README --- this file 9menu.1 --- man page for 9menu 9menu.c --- source code Imakefile --- a contributed Imakefile, from Bengt Kleberg Makefile.noimake --- a simple makefile. Licence ======= 9menu is free software, and is Copyright (c) 1994 by David Hogan and Arnold Robbins. Permission is granted to all sentient beings to use this software, to make copies of it, and to distribute those copies, provided that: (1) the copyright and licence notices are left intact (2) the recipients are aware that it is free software (3) any unapproved changes in functionality are either (i) only distributed as patches or (ii) distributed as a new program which is not called 9menu and whose documentation gives credit where it is due (4) the authors are not held responsible for any defects or shortcomings in the software, or damages caused by it. There is no warranty for this software. Have a nice day. -- Arnold Robbins arnold@skeeve.com larswm-7.5.3/README.9wm0000644000000000000000000001466610065667625014416 0ustar rootroot00000000000000 9wm Version 1.2 Copyright 1994-1996 David Hogan. What is 9wm? ============ 9wm is an X window manager which attempts to emulate the Plan 9 window manager 8-1/2 as far as possible within the constraints imposed by X. It provides a simple yet comfortable user interface, without garish decorations or title-bars. Or icons. And it's click-to-type. This will not appeal to everybody, but if you're not put off yet then read on. (And don't knock it until you've tried it.) One major difference between 9wm and 8-1/2 is that the latter provides windows of text with a typescript interface, and doesn't need to run a separate program to emulate a terminal. 9wm, as an X window manager, does require a separate program. For better 8-1/2 emulation, you should obtain Matthew Farrow's "9term" program (ftp://ftp.cs.su.oz.au/matty/unicode), version 1.6 or later (earlier versions don't cooperate with 9wm in implementing "hold mode"). Of course, you can run xterm under 9wm as well. What is 9wm not? ================ 9wm is not a virtual window manager. It is not customisable to any great extent. It is not large and unwieldy, and doesn't use the X toolkit. Requests to make it any of these things will be silently ignored (or flamed if I have had a bad day :-) If you want tvtwm or mwm, you know where to get them... Where do I get it? ================== The latest version of 9wm is held at ftp://ftp.cs.su.oz.au/dhog/9wm Author ====== 9wm was written by David Hogan (dhog@cs.su.oz.au), a postgraduate student at the Basser Department of Computer Science, University of Sydney (http://www.cs.su.oz.au/~dhog/). Licence ======= 9wm is free software, and is Copyright (c) 1994-1996 by David Hogan. Permission is granted to all sentient beings to use this software, to make copies of it, and to distribute those copies, provided that: (1) the copyright and licence notices are left intact (2) the recipients are aware that it is free software (3) any unapproved changes in functionality are either (i) only distributed as patches or (ii) distributed as a new program which is not called 9wm and whose documentation gives credit where it is due (4) the author is not held responsible for any defects or shortcomings in the software, or damages caused by it. There is no warranty for this software. Have a nice day. How do I compile/install it? ============================ Assuming your system is correctly configured, you should only need to run xmkmf to generate the Makefile, and then run make or make install. make install.man should copy the manpage (9wm.man) to the appropriate directory. If the make fails, complaining that the function _XShapeQueryExtension does not exist, try removing the "-DSHAPE" from the Imakefile, and run xmkmf and make again. If you don't have imake, or it is misconfigured, or you would prefer not to use it, try copying the file "Makefile.no-imake" to "Makefile", then edit the definitions in this Makefile to suit your system. This may require defining suitable compilation flags for your system (normally imake does this for you). For instance, on AIX you must include "-DBSD_INCLUDES" in CFLAGS. How do I use it? ================ See the manual page for details. You should probably read the man page for 9term as well. What if I find a bug? ===================== Please mail all bug reports to 9wm-bugs@plan9.cs.su.oz.au, so that I can incorporate fixes into the next release. If you can tell me how to fix it, all the better. Known Problems/Bugs =================== 9wm tries hard to emulate 8-1/2, but isn't 100% compatible. If you are an experienced 8-1/2 user, please be patient with it. One intentional difference between 9wm and 8-1/2 is in the behaviour of the menu when the last hidden item is unhidden. Under 8-1/2, when the menu is next used, it pops up with "New" selected. Under 9wm, the (new) last menu item will be selected. This is a feature. It may be confusing if you frequently switch between 9wm and 8-1/2. If you don't like this feature, email me for the one line fix. There have been some problems encountered when resizing 9term on some platforms. This turns out to be a problem in 9term (actually in libXg, to be precise). Newer versions of 9term should be immune to this, see matty@cs.su.oz.au if your 9term needs fixing. Some client programs do weird things. One of these is Frame Maker. It appears that if it has a modal dialog on the screen, then if any of its windows are current, all keypresses are redirected to the modal dialog. This is not 9wm's fault -- Frame Maker is doing this. Programs like Netscape Navigator like to put riddiculously long icon name properties on their windows, of the form "Netscape: blah blah". There is no way that I know of to stop netscape from doing this. For this reason, 9wm truncates labels at the first colon it finds. This keeps the button 3 menu from becoming excessively wide. Note that with same applications, you can use an iconName resource to set the label; this works well for "xman", whose default icon name of "Manual Browser" is a tad too long. See Also ======== http://www.cs.su.oz.au/~dhog/ The 9wm Home Page ftp://ftp.cs.su.oz.au/matty/unicode/ for source to 9term (get README first) ftp://plan9.att.com/plan9/unixsrc/sam/ for source && info on Rob Pike's editor "sam" ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/shell/rc for information on a publically available implementation of the Plan 9 shell "rc" for unix (or look in comp.unix.shell). ftp://viz.tamu.edu/pub/rc for source to the abovementioned implementation of rc. http://plan9.att.com/plan9/ http://plan9.att.com/magic/man2html/1/8%c2%bd for information on Plan 9 (including the 8-1/2 manual entry) Acknowledgements ================ Thanks to Rob Pike for writing the original 8-1/2 program (and before that, mux) which inspired the writing of 9wm. Thanks to John Mackin, whose gwm "wool code" for emulating mux was also an inspiration: I used it (and hacked it) until I got too frustrated with gwm's large memory requirements and lack of speed (sorry Colas!), and decided to write a dedicated program. Thanks to Matthew Farrow for writing 9term. A big thanks to Dave Edmondson for adding support for multi-screen displays. The following people helped beta test 9wm: John Mackin Noel Hunt Fred Curtis James Matthew Farrow Danny Yee Arnold Robbins Byron Rakitzis micro@cooper.edu larswm-7.5.3/sample.larswmrc0000644000000000000000000000403610075316655016041 0ustar rootroot00000000000000!!!!!!!!!!!!!!!!!!!!! ! .larswmrc example ! !!!!!!!!!!!!!!!!!!!!! ! These are the windows I want tiled ! larswm.dotileclass.0: XTerm~xterm larswm.dotileclass.1: navigator:browser~Mozilla larswm.dotileclass.2: Mozilla-bin ! Some tool windows ! larswm.toolclass.0: XLoad~xload larswm.toolclass.1: XBiff~xbiff larswm.toolclass.2: XClock~xclock ! Windows that should always stay above other windows ! larswm.floatclass.0: XCalc~xcalc larswm.floatclass.1: Gaim larswm.floatclass.2: larsmenu~larsmenu ! Windows that should be visible on all virtual desktops ! larswm.stickyclass.0: larsmenu~larsmenu ! Assign all new web browser windows to the WWW desktop ! larswm.dtclass.0: navigator:browser~Mozilla larswm.dtnum.0: 1 larswm.dtclass.1: Mozilla-bin larswm.dtnum.1: 1 ! Use a wider left track on the WWW desktop ! larswm.?.1.left_track_width: 80 ! Do not resize windows on the WWW desktop ! larswm.?.1.tile_resize: False ! Automatically shift focused window to the left track on WWW desktop ! larswm.?.1.skip_focus: False ! larswm Menu - Middle Mousebutton ! larswm.button2.application: larsmenu -popup '* LARSWM *:exit' 'R E S T A R T:larsremote restart' 'E X I T:larsremote exit' '* Exit Menu *:exit' ! Start Menu - Right Mousebutton ! larswm.button3.application: larsmenu -popup '* START *:exit' 'XTerm:xterm' 'Mozilla:mozilla' 'Emacs:emacs' 'GVim:gvim' 'Instant Messenger:gaim' 'Calculator:xcalc' '* Exit Menu *:exit' ! larswm Menu - Alt+Escape ! larswm.application.0: larsmenu -popup '* LARSWM *:exit' 'R E S T A R T:larsremote restart' 'E X I T:larsremote exit' '* Exit Menu *:exit' larswm.application_key.0: Escape larswm.application_mod.0: Alt ! Start Menu - Alt+Return ! larswm.application.1: larsmenu -popup '* START *:exit' 'XTerm:xterm' 'Mozilla:mozilla' 'Emacs:emacs' 'GVim:gvim' 'Instant Messenger:gaim' 'Calculator:xcalc' '* Exit Menu *:exit' larswm.application_key.1: Return larswm.application_mod.1: Alt ! XTerm - Shift+Control+Return ! larswm.application.2: xterm larswm.application_key.2: Return larswm.application_mod.2: Shift+Control larswm-7.5.3/sample.xsession0000755000000000000000000000101110065667625016060 0ustar rootroot00000000000000#!/bin/sh # # Copyright (c) 2004 Lars Bernhardsson, see README for licence details # # sample.xsession - Login script for larswm # # Clear root window settings and set background color xsetroot && xsetroot -solid lightgray # 2nd screen # xsetroot -display :0.1 && xsetroot -display :0.1 -solid lightgray # Start a couple of tools xload -geometry 96x48-0-0 & xbiff -geometry 48x48-100-0 & xclock -geometry 48x48-152-0 & # Start a background job that feeds date/time to larswm larsclock & # Start larswm. exec larswm larswm-7.5.3/tiling.c0000644000000000000000000010254310065667625014445 0ustar rootroot00000000000000/* Copyright (c) 2000-2004 Lars Bernhardsson, see README for license details */ #include #include #include #include #include #include #include #include "dat.h" #include "fns.h" /* * This file was added to David Hogan's 9wm source distribution. * It is written by Lars Bernhardsson, with inspiration from * such things as acme, wily, oberon and 100's of misplaced windows * over the years. :) */ /* only tile visible top level windows on the current desktop. */ #define DO_TILE(x,s) (((x)->screen == (s)) && (((x)->desktop == (s)->desktop) || (x)->issticky) && ((x)->trans == None) && (!(x)->isnotile) && (!(x)->istool) && (normal(x))) /* windows to raise when Raise Untiled is selected. */ #define DO_RAISE_NOTILE(x,s) (((x)->screen == (s)) && (((x)->desktop == (s)->desktop) || (x)->issticky) && ((x)->isnotile) && (normal(x))) /* global variables for this module */ static int track_x[64][2]; static int track_width[64][2]; #define MAX_RC 1024 static Client *rc[MAX_RC]; static int nrc; /* which tracks to reserve tool space in. */ static int res_track = 0; void getmouse (int *x, int *y, ScreenInfo * s) { Window dw1, dw2; int t1, t2; unsigned int t3; XQueryPointer (dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3); } void setmouse (int x, int y, ScreenInfo * s) { XWarpPointer (dpy, None, s->root, None, None, None, None, x, y); } void rev_clients (void) { Client *c; nrc = 0; for (c = clients; c && (nrc < MAX_RC); c = c->next) rc[nrc++] = c; } int is_float (Client * c) { int i; if (!c->class) return 0; for (i = 0; i < MAXFLOATCLASS; i++) { char *inst; if (!prefs.floatclass[i]) continue; if (strcmp (c->class, prefs.floatclass[i]) == 0) return 1; if (!c->instance) return 0; if (strcmp (c->instance, prefs.floatclass[i]) == 0) return 1; if ((inst = strchr (prefs.floatclass[i], '~'))) { inst++; if (strncmp (c->class, prefs.floatclass[i], strlen (c->class)) == 0) if (strncmp (c->instance, inst, strlen (c->instance)) == 0) return 1; } } return 0; } int is_sticky (Client * c) { int i; if (!c->class) return 0; for (i = 0; i < MAXSTICKYCLASS; i++) { char *inst; if (!prefs.stickyclass[i]) continue; if (strcmp (c->class, prefs.stickyclass[i]) == 0) return 1; if (!c->instance) return 0; if (strcmp (c->instance, prefs.stickyclass[i]) == 0) return 1; if ((inst = strchr (prefs.stickyclass[i], '~'))) { inst++; if (strncmp (c->class, prefs.stickyclass[i], strlen (c->class)) == 0) if (strncmp (c->instance, inst, strlen (c->instance)) == 0) return 1; } } return 0; } int is_tool (Client * c) { int i; if (!c->class) return 0; for (i = 0; i < MAXTOOLCLASS; i++) { char *inst; if (!prefs.toolclass[i]) continue; if (strcmp (c->class, prefs.toolclass[i]) == 0) return 1; if (!c->instance) return 0; if (strcmp (c->instance, prefs.toolclass[i]) == 0) return 1; if ((inst = strchr (prefs.toolclass[i], '~'))) { inst++; if (strncmp (c->class, prefs.toolclass[i], strlen (c->class)) == 0) if (strncmp (c->instance, inst, strlen (c->instance)) == 0) return 1; } } return 0; } int is_notile (Client * c) { int i; if (!c->class) return 1; for (i = 0; i < MAXNOTILECLASS; i++) { char *inst; if (!prefs.notileclass[i]) continue; if (strcmp (c->class, prefs.notileclass[i]) == 0) return 0; if (!c->instance) return 1; if (strcmp (c->instance, prefs.notileclass[i]) == 0) return 0; if ((inst = strchr (prefs.notileclass[i], '~'))) { inst++; if (strncmp (c->class, prefs.notileclass[i], strlen (c->class)) == 0) if (strncmp (c->instance, inst, strlen (c->instance)) == 0) return 0; } } return 1; } int is_dt (Client * c) { int i; if (!c->class) return -1; for (i = 0; i < MAXDTCLASS; i++) { char *inst; if (!prefs.dtclass[i]) continue; if (strcmp (c->class, prefs.dtclass[i]) == 0) return prefs.dtnum[i]; if (!c->instance) return -1; if (strcmp (c->instance, prefs.dtclass[i]) == 0) return prefs.dtnum[i]; if ((inst = strchr (prefs.dtclass[i], '~'))) { inst++; if (strncmp (c->class, prefs.dtclass[i], strlen (c->class)) == 0) if (strncmp (c->instance, inst, strlen (c->instance)) == 0) return prefs.dtnum[i]; } } return -1; } void toggle_isfloat (Client * c) { if (c) c->isfloat = !c->isfloat; update_tbar (); } void toggle_istool (Client * c) { if (c) c->istool = !c->istool; update_tbar (); } void toggle_issticky (Client * c) { if (c) c->issticky = !c->issticky; update_tbar (); } void toggle_inc (ScreenInfo * s) { if (s) s->bigmr[s->desktop] = !s->bigmr[s->desktop]; update_tbar (); } void toggle_clickthru (ScreenInfo * s) { if (s) s->clickthru[s->desktop] = !s->clickthru[s->desktop]; update_tbar (); } void toggle_tile_resize (ScreenInfo * s) { if (s) s->tile_resize[s->desktop] = !s->tile_resize[s->desktop]; update_tbar (); } void toggle_skip_focus (ScreenInfo * s) { if (s) s->skip_focus[s->desktop] = !s->skip_focus[s->desktop]; update_tbar (); } int count_clients (ScreenInfo * s) { Client *c; int i = 0; for (c = clients; c; c = c->next) if (DO_TILE (c, s)) i++; return i; } void find_tools (ScreenInfo * s) { Client *c; int min_y; int min_x, max_x; int t; int found = 0; if (!s) abort (); t = 0; max_x = -1; min_x = DisplayWidth (dpy, s->num) + 1; min_y = DisplayHeight (dpy, s->num) + 1; for (c = clients; c; c = c->next) { if (c->istool && (c->screen == s) && normal (c) && (c->issticky || (c->desktop == s->desktop)) && s->tile_resize[s->desktop]) { int x1 = c->x - BORDER; int y1 = c->y - BORDER; int x2 = c->x + c->dx + BORDER; found = 1; if (x1 < min_x) min_x = x1; if (x2 > max_x) max_x = x2; if (y1 < min_y) min_y = y1; } } if (found) { s->res_height = min_y - TILE_PAD; if (min_x < track_width[s->num][0]) t |= 1; if (max_x >= track_x[s->num][1]) t |= 2; res_track = t; } else { s->res_height = s->tile_height; res_track = 0; } } void calc_track_sizes (ScreenInfo * s) { int screen_width; if (!s) abort (); screen_width = DisplayWidth (dpy, s->num); track_x[s->num][0] = 0; track_width[s->num][0] = (s->left_track_width[s->desktop] * screen_width) / 100; track_x[s->num][1] = track_width[s->num][0]; track_width[s->num][1] = screen_width - track_width[s->num][0]; } void toggle_notile (ScreenInfo * s) { if (s->notile_raised[s->desktop]) raise_tile (s, 1); else raise_notile (s); } void raise_notile (ScreenInfo * s) { int i; rev_clients (); for (i = nrc - 1; i >= 0; i--) if (DO_RAISE_NOTILE (rc[i], s)) XMapRaised (dpy, rc[i]->parent); s->notile_raised[s->desktop] = 1; raise_tbar (s); if (s->notilefocused[s->desktop] && DO_RAISE_NOTILE (s->notilefocused[s->desktop], s) && !s->notilefocused[s->desktop]->isaside) { active (s->notilefocused[s->desktop]); } else { revert_same (s); } if (current) XMapRaised (dpy, current->parent); update_tbar (); } void raise_tile (ScreenInfo * s, int user) { Client *c; for (c = clients; c; c = c->next) if (DO_TILE (c, s)) XMapRaised (dpy, c->parent); s->notile_raised[s->desktop] = 0; raise_tbar (s); if (s->focused[s->desktop] && DO_TILE (s->focused[s->desktop], s)) { if (user || (!current && (mouse_on_screen () == s)) || (current && (current->screen == s))) { active (s->focused[s->desktop]); } } else { revert_same (s); } update_tbar (); } void tile_all (ScreenInfo * s) { Client *c; unsigned int screen_height_left, screen_height_right; unsigned int track_width_left, track_width_right; unsigned short clients_left, clients_right; unsigned short current_client = 0; unsigned short on_right = 0; if (!s) abort (); calc_track_sizes (s); find_tools (s); track_width_left = track_width[s->num][0]; track_width_right = track_width[s->num][1]; screen_height_left = (res_track & 1 ? s->res_height : s->tile_height); screen_height_right = (res_track & 2 ? s->res_height : s->tile_height); clients_right = count_clients (s); if (clients_right == 0) return; clients_left = 1; --clients_right; for (c = clients; c; c = c->next) { /* * WARNING * The variables "screen_height_left", "odx" and "ody" * have more than one purpose. */ if (DO_TILE (c, s)) { unsigned int x, y, width, height; unsigned int odx, ody; if (on_right) { x = track_width_left; y = screen_height_right - screen_height_left; height = screen_height_right / clients_right; width = track_width_right; if (++current_client < clients_right) { screen_height_left -= height; height -= TILE_PAD; } else height = screen_height_left; } else { x = y = 0; height = screen_height_left; width = track_width_left - TILE_PAD; /* * Here the purpose of * screen_height_left changes */ screen_height_left = screen_height_right; } height -= 2 * BORDER; width -= 2 * BORDER; c->isleft = on_right ? 0 : 1; odx = width; ody = height; /* * resize in given increments if the program * wishes this.. */ if (c->size.flags & PResizeInc) { width = c->min_dx + (((signed int) (width - c->min_dx) / c->size.width_inc) * c->size.width_inc); height = c->min_dy + (((signed int) (height - c->min_dy) / c->size.height_inc) * c->size.height_inc); } /* don't exceed this size */ if (c->size.flags & PMaxSize) { if (width > c->size.max_width) width = c->size.max_width; if (height > c->size.max_height) height = c->size.max_height; } /* * adjust track width if left window doesn't use * all of it or height left if a right window * doesn't use it all.. */ if (on_right) { if (ody != height) screen_height_left += ody - height; } else if (odx != width) { track_width_right += odx - width; track_width_left -= odx - width; } /* * The second meaning begins */ odx = c->dx; ody = c->dy; c->x = x; c->y = y; /* * if resize is true OR we're at the upper left corner * set size to maximum */ if (s->tile_resize[s->desktop] || !on_right) { c->dx = width; c->dy = height; } XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); /* give focus to window if appropriate */ if (c->isleft && (mouse_on_screen () == s) && !s->notile_raised[s->desktop]) { if (!current || !s->skip_focus[s->desktop] || !s->tile_resize[s->desktop]) active (c); } on_right = 1; } } if (current && !current->isnotile && !s->skip_focus[s->desktop]) { top (current); XMapRaised (dpy, current->parent); } if (!s->notile_raised[s->desktop]) { raise_tile (s, 0); } } void goto_desktop (ScreenInfo * s, int n) { if (s) { s->desktop = n; s->desktop %= prefs.desktops; update_desktop (s); } } void next_desktop (ScreenInfo * s) { if (s) { s->desktop++; s->desktop %= prefs.desktops; update_desktop (s); } } void next_desktop_drag (ScreenInfo * s) { Client *t; if (s) { if (current && (current->screen == s)) { t = current; t->desktop++; t->desktop %= prefs.desktops; next_desktop (s); active (t); if (t->isnotile) raise_notile (s); else raise_tile (s, 0); update_tbar (); } } } void prev_desktop (ScreenInfo * s) { if (s) { s->desktop += (prefs.desktops - 1); s->desktop %= prefs.desktops; update_desktop (s); } } void prev_desktop_drag (ScreenInfo * s) { Client *t; if (s) { if (current && (current->screen == s)) { t = current; t->desktop += (prefs.desktops - 1); t->desktop %= prefs.desktops; prev_desktop (s); active (t); if (t->isnotile) raise_notile (s); else raise_tile (s, 0); update_tbar (); } } } void move_hide (Client * c) { if (c) XMoveWindow (dpy, c->parent, DisplayWidth (dpy, c->screen->num), c->y); } void move_show (Client * c) { if (c) XMoveWindow (dpy, c->parent, c->x, c->y); } void update_desktop (ScreenInfo * s) { Client *c; for (c = clients; c; c = c->next) { if ((c->screen != s) || (c->parent == c->screen->root) || c->issticky || (c->state != NormalState)) continue; if (c->desktop == s->desktop) move_show (c); else move_hide (c); } if (!s->notile_raised[s->desktop] && s->focused[s->desktop]) active (s->focused[s->desktop]); else if (s->notile_raised[s->desktop] && s->notilefocused[s->desktop]) active (s->notilefocused[s->desktop]); else { revert_same (s); if (!current) revert_window (s); } tile_all (s); update_tbar (); } void revert_window (ScreenInfo * s) { Client *c; if (mouse_on_screen () != s) { if (current && (current->screen == s)) nofocus (); return; } if (prev_current) { c = prev_current; if (!c->istool && !c->isaside && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { if (c->isnotile) raise_notile (s); else raise_tile (s, 0); active (c); return; } } for (c = clients; c; c = c->next) { if (!c->istool && !c->isaside && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { if (c->isnotile) raise_notile (s); else raise_tile (s, 0); active (c); return; } } nofocus (); } void revert_same (ScreenInfo * s) { Client *c; if (mouse_on_screen () != s) { if (current && (current->screen == s)) nofocus (); return; } if (prev_current) { c = prev_current; if (!c->istool && !c->isaside && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); return; } } for (c = clients; c; c = c->next) { if (!c->istool && !c->isaside && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); return; } } nofocus (); } void prev_window (ScreenInfo * s) { Client *c; if (!current || !prev_current || (prev_current == current) || (prev_current->desktop != current->desktop) || (prev_current->isnotile != current->isnotile) || (!s->notile_raised[s->desktop] && !s->skip_focus[s->desktop])) { for (c = clients; c; c = c->next) { if (!c->istool && !c->isaside && (c != current) && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); if (c->isnotile || (!c->isnotile && !s->skip_focus[s->desktop])) { raise_tbar (s); top (c); XMapRaised (dpy, c->parent); tile_all (s); } return; } } return; } c = prev_current; if (!c->istool && !c->isaside && (c != current) && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); if (c->isnotile || (!c->isnotile && !s->skip_focus[s->desktop])) { raise_tbar (s); top (c); XMapRaised (dpy, c->parent); tile_all (s); } } } void next_window (ScreenInfo * s) { Client *c; if (s->notile_raised[s->desktop] || (!s->notile_raised[s->desktop] && !s->skip_focus[s->desktop])) { Client *last = 0; for (c = clients; c; c = c->next) { if (!c->istool && !c->isaside && (c != current) && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { last = c; } } if (last) { raise_tbar (s); top (last); XMapRaised (dpy, last->parent); if (last->isnotile) active (last); else tile_all (s); } return; } if (current && current->next && !s->notile_raised[s->desktop] && s->skip_focus[s->desktop]) { for (c = current->next; c; c = c->next) { if (!c->istool && !c->isaside && (c != current) && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); if (c->isnotile || (!c->isnotile && !s->skip_focus[s->desktop])) { raise_tbar (s); XMapRaised (dpy, c->parent); tile_all (s); } return; } } } for (c = clients; c; c = c->next) { if (!c->istool && !c->isaside && (c != current) && (c->isnotile == s->notile_raised[s->desktop]) && (DO_TILE (c, s) || DO_RAISE_NOTILE (c, s))) { active (c); if (c->isnotile || (!c->isnotile && !s->skip_focus[s->desktop])) { raise_tbar (s); top (c); XMapRaised (dpy, c->parent); tile_all (s); } return; } } } void prev_screen (ScreenInfo * s) { ScreenInfo *ns; int cur; if (!s) abort (); cur = s->num; if (--cur < 0) cur = num_screens - 1; raise_tbar (s); ns = &screens[cur]; setmouse (DisplayWidth (dpy, cur) / 2, DisplayHeight (dpy, cur) - 2, ns); if (!ns->notile_raised[ns->desktop] && ns->focused[ns->desktop]) active (ns->focused[ns->desktop]); else if (ns->notile_raised[ns->desktop] && ns->notilefocused[ns->desktop]) active (ns->notilefocused[ns->desktop]); else { revert_same (ns); if (!current) revert_window (ns); } } void next_screen (ScreenInfo * s) { ScreenInfo *ns; int cur; if (!s) abort (); cur = s->num; if (++cur >= num_screens) cur = 0; raise_tbar (s); ns = &screens[cur]; setmouse (DisplayWidth (dpy, cur) / 2, DisplayHeight (dpy, cur) - 2, ns); if (!ns->notile_raised[ns->desktop] && ns->focused[ns->desktop]) active (ns->focused[ns->desktop]); else if (ns->notile_raised[ns->desktop] && ns->notilefocused[ns->desktop]) active (ns->notilefocused[ns->desktop]); else { revert_same (ns); if (!current) revert_window (ns); } } ScreenInfo * mouse_on_screen (void) { int i; if (num_screens == 1) return &screens[0]; for (i = 0; i < num_screens; i++) { Window root, child; int rx, ry, wx, wy; unsigned int mask; if (XQueryPointer (dpy, screens[i].root, &root, &child, &rx, &ry, &wx, &wy, &mask) == True) return &screens[i]; } return 0; } void shrink_left (ScreenInfo * s) { if (s) { s->left_track_width[s->desktop] -= 5; if (s->left_track_width[s->desktop] < 5) s->left_track_width[s->desktop] = 5; tile_all (s); } } void grow_left (ScreenInfo * s) { if (s) { s->left_track_width[s->desktop] += 5; if (s->left_track_width[s->desktop] > 95) s->left_track_width[s->desktop] = 95; tile_all (s); } } void max_left (ScreenInfo * s) { if (s) { s->left_track_width[s->desktop] = 95; tile_all (s); } } void restore_left (ScreenInfo * s) { if (s) { s->left_track_width[s->desktop] = prefs.left_track_width[s->num][s->desktop]; tile_all (s); } } void move_northwest (Client * c) { if (c && c->isnotile) { c->x = 0; c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_north (Client * c) { if (c && c->isnotile) { c->x = (DisplayWidth (dpy, c->screen->num) / 2) - (c->dx / 2) - BORDER; c->y = 0; if (c->x < 0) c->x = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_northeast (Client * c) { if (c && c->isnotile) { c->x = (DisplayWidth (dpy, c->screen->num)) - (c->dx) - (2 * BORDER); c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_west (Client * c) { if (c && c->isnotile) { c->x = 0; c->y = (c->screen->tile_height / 2) - (c->dy / 2) - BORDER; if (c->y < 0) c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_center (Client * c) { if (c && c->isnotile) { c->x = (DisplayWidth (dpy, c->screen->num) / 2) - (c->dx / 2) - BORDER; c->y = (c->screen->tile_height / 2) - (c->dy / 2) - BORDER; if (c->x < 0) c->x = 0; if (c->y < 0) c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_east (Client * c) { if (c && c->isnotile) { c->x = DisplayWidth (dpy, c->screen->num) - c->dx - (2 * BORDER); c->y = (c->screen->tile_height / 2) - (c->dy / 2) - BORDER; if (c->y < 0) c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_southwest (Client * c) { if (c && c->isnotile) { c->x = 0; c->y = c->screen->tile_height - c->dy - (2 * BORDER); XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_south (Client * c) { if (c && c->isnotile) { c->x = (DisplayWidth (dpy, c->screen->num) / 2) - (c->dx / 2) - BORDER; c->y = c->screen->tile_height - c->dy - (2 * BORDER); if (c->x < 0) c->x = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_southeast (Client * c) { if (c && c->isnotile) { c->x = DisplayWidth (dpy, c->screen->num) - c->dx - (2 * BORDER); c->y = c->screen->tile_height - c->dy - (2 * BORDER); XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_up (Client * c) { if (c && c->isnotile) { if (c->screen->bigmr[c->screen->desktop]) c->y -= (c->screen->tile_height / 20); else c->y--; if (c->y < 0) c->y = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_down (Client * c) { if (c && c->isnotile) { int max_y = c->screen->tile_height - c->dy - (2 * BORDER); if (c->screen->bigmr[c->screen->desktop]) c->y += (c->screen->tile_height / 20); else c->y++; if (c->y > max_y) c->y = max_y; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_left (Client * c) { if (c && c->isnotile) { if (c->screen->bigmr[c->screen->desktop]) c->x -= (DisplayWidth (dpy, c->screen->num) / 20); else c->x--; if (c->x < 0) c->x = 0; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void move_right (Client * c) { if (c && c->isnotile) { int max_x = DisplayWidth (dpy, c->screen->num) - c->dx - (2 * BORDER); if (c->screen->bigmr[c->screen->desktop]) c->x += (DisplayWidth (dpy, c->screen->num) / 20); else c->x++; if (c->x > max_x) c->x = max_x; XMoveWindow (dpy, c->parent, c->x, c->y); sendconfig (c); } } void zoom (Client * c, int dimension) { if (c) { if (!c->isnotile) { if (c->screen->notile_raised[c->screen->desktop]) toggle_notile (c->screen); if (c->isleft) { Client *p; for (p = clients->next; p; p = p->next) { if (!p->istool && (p != current) && (p->isnotile == p->screen->notile_raised[p->screen->desktop]) && (DO_TILE (p, c->screen) || DO_RAISE_NOTILE (p, c->screen))) { active (p); break; } } top (current); tile_all (c->screen); } else { top (c); tile_all (c->screen); } } else if (c->iszoom == ZOOM_SELECT) { move_select (c, 0); } else if (c->iszoom == ZOOM_NORMAL) { c->x = c->zx; c->y = c->zy; c->dx = c->zdx; c->dy = c->zdy; XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); c->iszoom = ZOOM_UNZOOMED; } else { int height; int width; if (dimension & DIM_OUTSIDE) { width = DisplayWidth (dpy, c->screen->num); height = DisplayHeight (dpy, c->screen->num); } else { height = c->screen->tile_height - (2 * BORDER); width = DisplayWidth (dpy, c->screen->num) - (2 * BORDER); } if (c->size.flags & PResizeInc) { width = c->min_dx + (width - c->min_dx) / c->size.width_inc * c->size.width_inc; height = c->min_dy + (height - c->min_dy) / c->size.height_inc * c->size.height_inc; } if (c->size.flags & PMaxSize) { if (width > c->size.max_width) width = c->size.max_width; if (height > c->size.max_height) height = c->size.max_height; } c->zx = c->x; c->zy = c->y; c->zdx = c->dx; c->zdy = c->dy; if (dimension & DIM_HORIZ) { c->dx = width; if (dimension & DIM_OUTSIDE) c->x = -BORDER; else c->x = (DisplayWidth (dpy, c->screen->num) / 2) - (c->dx / 2) - BORDER; } if (dimension & DIM_VERT) { c->dy = height; if (dimension & DIM_OUTSIDE) c->y = -BORDER; else c->y = (c->screen->tile_height / 2) - (c->dy / 2) - BORDER; } XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); c->iszoom = ZOOM_NORMAL; } update_tbar (); } } void grow (Client * c, int dimension, int m) { int h, w, dh, dw, x, y; int odx, ody, want_w, want_h; int ddx, ddy; if (!c || !dimension) return; if (!c->isnotile) { if ((dimension == DIM_HORIZ) || (dimension == (DIM_HORIZ | DIM_VERT))) { if (m > 0) grow_left (c->screen); else shrink_left (c->screen); } else if (dimension == DIM_VERT) { if (m > 0) max_left (c->screen); else restore_left (c->screen); } return; } x = c->x; y = c->y; w = odx = c->dx; h = ody = c->dy; dw = DisplayWidth (dpy, c->screen->num) - (2 * BORDER); dh = c->screen->tile_height - (2 * BORDER); if (c->screen->bigmr[c->screen->desktop]) { ddx = (dw / 20); ddy = (dh / 20); } else if (c->size.flags & PResizeInc) { ddx = c->size.width_inc; ddy = c->size.height_inc; } else { ddx = 2; ddy = 2; } if (dimension & DIM_HORIZ) { x -= (ddx / 2) * m; w += ddx * m; if ((x + w) > dw) x = dw - w; if (x < 0) x = 0; if ((x + w) > dw) w = dw; if (w < 1) w = 1; } if (dimension & DIM_VERT) { y -= (ddy / 2) * m; h += ddy * m; if ((y + h) > dh) y = dh - h; if (y < 0) y = 0; if ((y + h) > dh) h = dh; if (h < 1) h = 1; } want_w = w; want_h = h; if (c->size.flags & PResizeInc) { w = c->min_dx + (w - c->min_dx) / c->size.width_inc * c->size.width_inc; h = c->min_dy + (h - c->min_dy) / c->size.height_inc * c->size.height_inc; } if (c->size.flags & PMinSize) { if (w < c->size.min_width) w = c->size.min_width; if (h < c->size.min_height) h = c->size.min_height; } if (c->size.flags & PMaxSize) { if (w > c->size.max_width) w = c->size.max_width; if (h > c->size.max_height) h = c->size.max_height; } x += ((want_w - w) / 2); y += ((want_h - h) / 2); if ((w == odx) && (h == ody)) return; if (w != odx) { c->x = x; c->dx = w; } if (h != ody) { c->y = y; c->dy = h; } XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); } void move_select (Client * c, int untiled) { int h, w, dh, dw, x, y; int odx, ody; if (!c || !c->isnotile || c->isaside) return; odx = c->dx; ody = c->dy; if (c->iszoom == ZOOM_NORMAL) { zoom (c, DIM_HORIZ | DIM_VERT); return; } else if (c->iszoom == ZOOM_SELECT) { c->x = c->zx; c->y = c->zy; c->dx = c->zdx; c->dy = c->zdy; XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); XMapRaised (dpy, c->parent); top (c); active (c); if (!c->screen->notile_raised[c->screen->desktop]) raise_notile (c->screen); c->iszoom = ZOOM_UNZOOMED; update_tbar (); return; } x = c->x; y = c->y; w = odx; h = ody; dh = c->screen->tile_height - (2 * BORDER); dw = DisplayWidth (dpy, c->screen->num) - (2 * BORDER); if (untiled) /* window that just stopped being tiled, restore original size */ { if ((c->size.flags & PSize) && ((c->size.height != ody) || (c->size.width != odx))) { h = c->size.height; w = c->size.width; } else /* emacs changes size hints when you resize it... odd. */ { h = dh / 2; w = dw / 2; } } else { h = dh; w = (17 * h) / 22; /* US Letter ratio */ } if (w > dw) /* for screens with non-standard ratios */ w = dw; if (h > dh) /* for when hints says taller than screen */ h = dh; if (c->size.flags & PResizeInc) { w = c->min_dx + (w - c->min_dx) / c->size.width_inc * c->size.width_inc; h = c->min_dy + (h - c->min_dy) / c->size.height_inc * c->size.height_inc; } if (c->size.flags & PMinSize) { if (w < c->size.min_width) w = c->size.min_width; if (h < c->size.min_height) h = c->size.min_height; } if (c->size.flags & PMaxSize) { if (w > c->size.max_width) w = c->size.max_width; if (h > c->size.max_height) h = c->size.max_height; } x = (DisplayWidth (dpy, c->screen->num) / 2) - (w / 2) - BORDER; y = (c->screen->tile_height / 2) - (h / 2) - BORDER; if (c->x < 0) c->x = 0; if (c->y < 0) c->y = 0; c->zx = c->x; c->zy = c->y; c->zdx = c->dx; c->zdy = c->dy; if (w != odx) { c->x = x; c->dx = w; } if (h != ody) { c->y = y; c->dy = h; } XMoveResizeWindow (dpy, c->parent, c->x, c->y, c->dx + (2 * BORDER), c->dy + (2 * BORDER)); XResizeWindow (dpy, c->window, c->dx, c->dy); sendconfig (c); XMapRaised (dpy, c->parent); top (c); active (c); if (!c->screen->notile_raised[c->screen->desktop]) raise_notile (c->screen); if (untiled) /* if just stopped being tiled, do not count this as zoomed */ c->iszoom = ZOOM_UNZOOMED; else c->iszoom = ZOOM_SELECT; update_tbar (); } int count_aside (ScreenInfo * s) { int i = 0; Client *c; if (!s) return 0; for (c = clients; c; c = c->next) { if (c->isaside && DO_RAISE_NOTILE (c, s)) { i++; } } return i; } Client * find_aside (ScreenInfo * s) { Client *c; if (!s) return (Client *) 0; for (c = clients; c; c = c->next) { if (c->isaside && DO_RAISE_NOTILE (c, s)) { return c; } } return (Client *) 0; } void arrange_aside (ScreenInfo * s) { int wnum = 0; int wcount; int ystep; Client *c; if (!s) return; wcount = count_aside (s); if (wcount < 1) { return; } ystep = s->tile_height / wcount; for (c = clients; c; c = c->next) { if (c->isaside && DO_RAISE_NOTILE (c, s)) { c->y = ystep * wnum++; XMapRaised (dpy, c->parent); XMoveWindow (dpy, c->parent, c->x, c->y); } } } void move_aside (ScreenInfo * s, Client * c) { if (!s) return; if (!c || !c->isnotile || c->istool) { Client *t = find_aside (s); if (t) { raise_notile (s); XMapRaised (dpy, s->barwin); move_aside (s, t); } return; } if (c->isaside) { c->x = c->ax; c->y = c->ay; c->isaside = 0; if (s->notile_raised[s->desktop] != c->isnotile) toggle_notile (s); arrange_aside (s); active (c); raise_tbar (s); XMapRaised (dpy, c->parent); XMoveWindow (dpy, c->parent, c->x, c->y); } else { c->ax = c->x; c->ay = c->y; c->x = (95 * DisplayWidth (dpy, s->num)) / 100; c->isaside = 1; arrange_aside (s); revert_window (s); XMapRaised (dpy, s->barwin); if (current) XMapRaised (dpy, current->parent); } } void move_aside_other (ScreenInfo * s) { Client *c; if (!s || !current || !current->isnotile) return; for (c = clients; c; c = c->next) { if ((c != current) && !c->isaside && !c->istool && DO_RAISE_NOTILE (c, s)) { c->ax = c->x; c->ay = c->y; c->x = (95 * DisplayWidth (dpy, s->num)) / 100; c->isaside = 1; } } arrange_aside (s); XMapRaised (dpy, s->barwin); XMapRaised (dpy, current->parent); } void move_aside_clear (ScreenInfo * s, Client * c) { if (s && c && (c->screen == s) && c->isnotile && normal (c) && !c->isaside) move_aside (s, c); } void move_sd (Client * c) { if (!c) return; c->iszoom = ZOOM_UNZOOMED; if (c->isnotile) { c->isnotile = 0; raise_tile (c->screen, 0); top (c); active (c); tile_all (c->screen); } else { c->isnotile = 1; tile_all (c->screen); raise_notile (c->screen); move_select (c, 1); } }