implement support for multimonitor setups; bump version to 1.3.0
This commit is contained in:
parent
b171a66b5c
commit
69da0d7c77
16 changed files with 711 additions and 247 deletions
34
README.md
34
README.md
|
@ -8,13 +8,14 @@
|
||||||
![pseudotiling](./screenshots/pseudotiling.png)
|
![pseudotiling](./screenshots/pseudotiling.png)
|
||||||
|
|
||||||
### About
|
### About
|
||||||
`ryudo` is a fork of Russ Cox's Rio, itself a fork of David Hogan's 9wm.
|
`ryudo` is a fork of Russ Cox's `rio`, itself a fork of David Hogan's `9wm`.
|
||||||
The primary additions I've made are:
|
The primary additions I've made are:
|
||||||
|
|
||||||
- `urxvt`, `konsole`, and `Alacritty` are detected as proper terminal programs for sweeping out new windows
|
- `urxvt`, `konsole`, and `Alacritty` are detected as proper terminal programs for sweeping out new windows
|
||||||
- `urxvt` is the default terminal emulator (still tries `9term` and then `xterm` if no dice)
|
- `urxvt` is the default terminal emulator (still tries `9term` and then `xterm` if no dice)
|
||||||
- Window spawning behavior has been made more natural -- windows shouldn't spawn partially offscreen like with `rio`
|
- Window spawning behavior has been made more natural -- windows shouldn't spawn partially offscreen like with `rio`
|
||||||
- Customizable colors, borders, fonts, gaps, and keybinds in `config.h`
|
- Customizable colors, borders, fonts, gaps, and keybinds in `config.h`
|
||||||
|
- Multimonitor support via `Xrandr`
|
||||||
- Default keybindings:
|
- Default keybindings:
|
||||||
+ New Terminal: Super+Slash
|
+ New Terminal: Super+Slash
|
||||||
+ Destroy: Super+D
|
+ Destroy: Super+D
|
||||||
|
@ -23,6 +24,7 @@ The primary additions I've made are:
|
||||||
+ Maximize: Super+M
|
+ Maximize: Super+M
|
||||||
+ moVe: Super+V
|
+ moVe: Super+V
|
||||||
+ Reshape: Super+R
|
+ Reshape: Super+R
|
||||||
|
+ wrAngle: Super+A
|
||||||
+ Stick: Super+S
|
+ Stick: Super+S
|
||||||
+ Snap Left: Super+H
|
+ Snap Left: Super+H
|
||||||
+ Snap Right: Super+L
|
+ Snap Right: Super+L
|
||||||
|
@ -35,7 +37,7 @@ The primary additions I've made are:
|
||||||
+ Snap Big Center: Super+C
|
+ Snap Big Center: Super+C
|
||||||
+ Snap Floating Center: Super+Shift+C
|
+ Snap Floating Center: Super+Shift+C
|
||||||
+ Virtual Desk++: Super+Right
|
+ Virtual Desk++: Super+Right
|
||||||
+ Virtual Desk--: Super+Left
|
+ Virtual Desk—: Super+Left
|
||||||
- Other new features customizable by `config.h`:
|
- Other new features customizable by `config.h`:
|
||||||
+ Show/hide 'Stick' Button3 menuitem
|
+ Show/hide 'Stick' Button3 menuitem
|
||||||
+ `AUTOSTICK` list of windows to spawn sticky by default and not focus (pseudo-panel/dock windows)
|
+ `AUTOSTICK` list of windows to spawn sticky by default and not focus (pseudo-panel/dock windows)
|
||||||
|
@ -45,31 +47,39 @@ The primary additions I've made are:
|
||||||
+ Option to swap the keyboard shortcuts between "Snap Big Center" and "Snap Floating Center" (and the preferred behavior for terminals launched by keyboard)
|
+ Option to swap the keyboard shortcuts between "Snap Big Center" and "Snap Floating Center" (and the preferred behavior for terminals launched by keyboard)
|
||||||
|
|
||||||
The name "Ryudo" is a nod to "Rio" and a Japanese word for "flow."
|
The name "Ryudo" is a nod to "Rio" and a Japanese word for "flow."
|
||||||
Using Ryudo should feel very natural -- you can do things with keyboard or
|
Using `ryudo` should feel very natural -- you can do things with keyboard or
|
||||||
mouse depending on the situation. Terminal launching can be done with mouse
|
mouse depending on the situation. Terminal launching can be done with mouse
|
||||||
using the popup menu, or using the keyboard, which will spawn a terminal
|
using the popup menu, or using the keyboard, which will spawn a terminal
|
||||||
window centered (its exact geometry is configurable via `config.h`).
|
window centered (its exact geometry is configurable via `config.h`).
|
||||||
|
|
||||||
### Dependencies, Building, Installation
|
### Dependencies, Building, Installation
|
||||||
Being forked from Rio, Ryudo requires `plan9port`, `Xlib`, and `Xt`.
|
|
||||||
If you enable notifications, they need `libnotify`.
|
Running and building require the following:
|
||||||
(With the exception of `plan9port`, you need the development headers for all the dependencies in addition to the libraries themselves in order to compile).
|
|
||||||
|
* a full `plan9port` installation
|
||||||
|
* `libX11` and development headers
|
||||||
|
* `libXT` and development headers
|
||||||
|
* `libXrandr` and development headers
|
||||||
|
|
||||||
|
If virtual desktop switching notification is enabled, it requires
|
||||||
|
|
||||||
|
* `libnotify` and development headers
|
||||||
|
|
||||||
Build with `build.sh` (calls `mk` and does some other magic), and install with `install.sh` (will install to a local folder if run as a normal user, or to your `$PLAN9/bin/` plus session wrapper in `/usr/bin` and `.desktop` file in `/usr/share/xsessions/` if run as root).
|
Build with `build.sh` (calls `mk` and does some other magic), and install with `install.sh` (will install to a local folder if run as a normal user, or to your `$PLAN9/bin/` plus session wrapper in `/usr/bin` and `.desktop` file in `/usr/share/xsessions/` if run as root).
|
||||||
|
|
||||||
If you have trouble building, you might need to edit the `mkfile` at line 2
|
If you have trouble building, you might need to edit the `mkfile` at line 2 to point to the proper location of your plan9port's `mkwsysrules.sh`, or edit the compiler flags (`CFLAGS`) linker flags (`LDFLAGS`) to point to your libraries' real location.
|
||||||
to point to the proper location of your plan9port's `mkwsysrules.sh`.
|
|
||||||
|
|
||||||
### Bugs and Caveats
|
### Bugs and Caveats
|
||||||
Of the bugs and caveats not already mentioned in Rio's readme:
|
Of the bugs and caveats not already mentioned in `rio`'s README:
|
||||||
|
|
||||||
- Rendering of windows with RGBA surfaces is bound to RGB space (ie, transparency cannot be set on a per-pixel level beyond a binary resolution)
|
- No per-pixel alpha support beyond `XShape` extension.
|
||||||
- Switching back and forth between virtual desktops very quickly can cause some windows to glitch out, lose their parent, and become unfocusable (doesn't happen if switching just in one direction).
|
- Switching back and forth between virtual desktops very quickly can cause some windows to glitch out, lose their parent (border), and become unfocusable.
|
||||||
- Multimonitor setups are treated like one giant monitor. This is on the short list.
|
|
||||||
- Some applications that render fullscreen or dedicated OSD windows (Virtualbox, Zoom, etc) will need to be manually maximized to fix their alignment (in the former case) or otherwise misbehave.
|
- Some applications that render fullscreen or dedicated OSD windows (Virtualbox, Zoom, etc) will need to be manually maximized to fix their alignment (in the former case) or otherwise misbehave.
|
||||||
- Probably more!
|
- Probably more!
|
||||||
|
|
||||||
### Legacy
|
### Legacy
|
||||||
|
|
||||||
|
The original README from `rio`, (which contains the original README from 9wm) is in this repository. See [README.rio](./readme.rio)
|
||||||
This is David Hogan's 9wm updated to behave more like
|
This is David Hogan's 9wm updated to behave more like
|
||||||
Plan 9's rio. Since I cannot get approval for the changes
|
Plan 9's rio. Since I cannot get approval for the changes
|
||||||
and I'd prefer not to resort to patches, I have renamed it "rio".
|
and I'd prefer not to resort to patches, I have renamed it "rio".
|
||||||
|
|
201
README.rio
Normal file
201
README.rio
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
This is David Hogan's 9wm updated to behave more like
|
||||||
|
Plan 9's rio. Since I cannot get approval for the changes
|
||||||
|
and I'd prefer not to resort to patches, I have renamed it "rio".
|
||||||
|
|
||||||
|
Current incompatibilities that would be nice to fix:
|
||||||
|
|
||||||
|
- The command-line options should be made more like Plan 9.
|
||||||
|
|
||||||
|
- Should work out a protocol between 9term and rio so that:
|
||||||
|
* 9term can tell rio to blue its border during hold mode
|
||||||
|
|
||||||
|
- Should change window focus on b2/b3 clicks and then
|
||||||
|
pass along the click event to the now-focused window.
|
||||||
|
|
||||||
|
- Should change 9term to redirect b3 clicks to rio so that rio
|
||||||
|
can put up the usual b3 menu.
|
||||||
|
|
||||||
|
Axel Belinfante contributed the code to handle border grabbing
|
||||||
|
for resize and various other improvements.
|
||||||
|
|
||||||
|
The original README is below.
|
||||||
|
|
||||||
|
- russ cox
|
||||||
|
rsc@swtch.com
|
||||||
|
30 march 2004
|
||||||
|
|
||||||
|
|
||||||
|
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
|
76
client.c
76
client.c
|
@ -78,8 +78,10 @@ void active(Client* c) {
|
||||||
fprintf(stderr, "ryudo: active(c==0)\n");
|
fprintf(stderr, "ryudo: active(c==0)\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (c == current)
|
if (c == current) {
|
||||||
|
draw_border(c, 1);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
#ifdef AUTOSTICK
|
#ifdef AUTOSTICK
|
||||||
if (isautostick(c))
|
if (isautostick(c))
|
||||||
return;
|
return;
|
||||||
|
@ -155,7 +157,7 @@ void top(Client* c) {
|
||||||
}
|
}
|
||||||
l = &cc->next;
|
l = &cc->next;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c);
|
fprintf(stderr, "ryudo: %p not on client list in top()\n", (void*)c);
|
||||||
}
|
}
|
||||||
|
|
||||||
Client* getclient(Window w, int create) {
|
Client* getclient(Window w, int create) {
|
||||||
|
@ -209,20 +211,16 @@ void rmclient(Client* c) {
|
||||||
if (hidden(c))
|
if (hidden(c))
|
||||||
unhidec(c, 0);
|
unhidec(c, 0);
|
||||||
|
|
||||||
|
if (current == c) {
|
||||||
|
current = 0;
|
||||||
|
setactive(c, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (c->parent != c->screen->root)
|
if (c->parent != c->screen->root)
|
||||||
XDestroyWindow(dpy, c->parent);
|
XDestroyWindow(dpy, c->parent);
|
||||||
|
|
||||||
c->parent = c->window = None; /* paranoia */
|
c->parent = c->window = None; /* paranoia */
|
||||||
if (current == c) {
|
|
||||||
current = c->revert;
|
|
||||||
if (current == 0)
|
|
||||||
nofocus();
|
|
||||||
else {
|
|
||||||
if (current->screen != c->screen)
|
|
||||||
cmapnofocus(c->screen);
|
|
||||||
setactive(current, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c->ncmapwins != 0) {
|
if (c->ncmapwins != 0) {
|
||||||
XFree((char*)c->cmapwins);
|
XFree((char*)c->cmapwins);
|
||||||
free((char*)c->wmcmaps);
|
free((char*)c->wmcmaps);
|
||||||
|
@ -276,11 +274,38 @@ void dump_clients(void) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void shuffleonmonitor(int m) {
|
||||||
|
Client **l, *c;
|
||||||
|
XRRMonitorInfo monitor;
|
||||||
|
|
||||||
|
if (clients == 0 || clients->next == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
c = 0;
|
||||||
|
/*for(c=clients; c->next; c=c->next) */
|
||||||
|
/* ; */
|
||||||
|
for (l = &clients; (*l)->next; l = &(*l)->next)
|
||||||
|
#ifdef AUTOSTICK
|
||||||
|
if ((*l)->state == 1 && !isautostick(*l) && getmonitorbyclient(*l) == m)
|
||||||
|
c = *l;
|
||||||
|
#else
|
||||||
|
if ((*l)->state == 1 && getmonitorbyclient(*l) == m)
|
||||||
|
c = *l;
|
||||||
|
#endif
|
||||||
|
if (c == 0)
|
||||||
|
return;
|
||||||
|
XMapRaised(dpy, c->parent);
|
||||||
|
top(c);
|
||||||
|
active(c);
|
||||||
|
if (zoom) {
|
||||||
|
monitor = monitorinfo[getmonitorbyclient(c)];
|
||||||
|
quickreshape(c, monitor.x, monitor.y, monitor.width, monitor.height, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void shuffle(int up) {
|
void shuffle(int up) {
|
||||||
Client **l, *c;
|
Client **l, *c;
|
||||||
static XWindowAttributes ra;
|
XRRMonitorInfo monitor;
|
||||||
|
|
||||||
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
|
||||||
|
|
||||||
if (clients == 0 || clients->next == 0)
|
if (clients == 0 || clients->next == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -290,10 +315,14 @@ void shuffle(int up) {
|
||||||
/* ; */
|
/* ; */
|
||||||
for (l = &clients; (*l)->next; l = &(*l)->next)
|
for (l = &clients; (*l)->next; l = &(*l)->next)
|
||||||
#ifdef AUTOSTICK
|
#ifdef AUTOSTICK
|
||||||
if ((*l)->state == 1 && !isautostick(*l))
|
if (
|
||||||
|
(*l)->state == 1 && !isautostick(*l) &&
|
||||||
|
(!current || getmonitorbyclient(*l) == getmonitorbyclient(current)))
|
||||||
c = *l;
|
c = *l;
|
||||||
#else
|
#else
|
||||||
if ((*l)->state == 1)
|
if (
|
||||||
|
(*l)->state == 1 &&
|
||||||
|
(!current || getmonitorbyclient(*l) == getmonitorbyclient(current)))
|
||||||
c = *l;
|
c = *l;
|
||||||
#endif
|
#endif
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
|
@ -302,12 +331,8 @@ void shuffle(int up) {
|
||||||
top(c);
|
top(c);
|
||||||
active(c);
|
active(c);
|
||||||
if (zoom) {
|
if (zoom) {
|
||||||
quickreshape(
|
monitor = monitorinfo[getmonitorbyclient(c)];
|
||||||
c,
|
quickreshape(c, monitor.x, monitor.y, monitor.width, monitor.height, 1);
|
||||||
-BORDER,
|
|
||||||
-BORDER,
|
|
||||||
ra.width + 2 * BORDER,
|
|
||||||
ra.height + 2 * BORDER);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
c = clients;
|
c = clients;
|
||||||
|
@ -385,3 +410,8 @@ void ensureactive() {
|
||||||
if (!current)
|
if (!current)
|
||||||
shuffle(0);
|
shuffle(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ensureactiveonmonitor(int monitor) {
|
||||||
|
if (!current)
|
||||||
|
shuffleonmonitor(monitor);
|
||||||
|
}
|
14
cursor.c
14
cursor.c
|
@ -172,17 +172,17 @@ void initcurs(ScreenInfo* s) {
|
||||||
XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "black", &bl, &dummy);
|
XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "black", &bl, &dummy);
|
||||||
XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "white", &wh, &dummy);
|
XAllocNamedColor(dpy, DefaultColormap(dpy, s->num), "white", &wh, &dummy);
|
||||||
|
|
||||||
if (nostalgia) {
|
/*if (nostalgia) {
|
||||||
s->arrow = getcursor(&blitarrow, s);
|
s->arrow = getcursor(&blitarrow, s);
|
||||||
s->target = getcursor(&blittarget, s);
|
s->target = getcursor(&blittarget, s);
|
||||||
s->sweep0 = getcursor(&blitsweep, s);
|
s->sweep0 = getcursor(&blitsweep, s);
|
||||||
s->boxcurs = getcursor(&blitsweep, s);
|
s->boxcurs = getcursor(&blitsweep, s);
|
||||||
} else {
|
} else {*/
|
||||||
s->arrow = getcursor(&bigarrow, s);
|
s->arrow = getcursor(&bigarrow, s);
|
||||||
s->target = getcursor(&sightdata, s);
|
s->target = getcursor(&sightdata, s);
|
||||||
s->sweep0 = getcursor(&sweep0data, s);
|
s->sweep0 = getcursor(&sweep0data, s);
|
||||||
s->boxcurs = getcursor(&boxcursdata, s);
|
s->boxcurs = getcursor(&boxcursdata, s);
|
||||||
}
|
//}
|
||||||
|
|
||||||
s->root_pixmap = XCreatePixmapFromBitmapData(
|
s->root_pixmap = XCreatePixmapFromBitmapData(
|
||||||
dpy,
|
dpy,
|
||||||
|
|
7
dat.h
7
dat.h
|
@ -1,10 +1,5 @@
|
||||||
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
|
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
|
||||||
#ifndef MAX_MONITORS
|
|
||||||
#define MAX_MONITORS 8
|
|
||||||
#endif
|
|
||||||
#ifndef BORDER
|
|
||||||
#define BORDER _border
|
|
||||||
#endif
|
|
||||||
#define CORNER _corner
|
#define CORNER _corner
|
||||||
#define INSET _inset
|
#define INSET _inset
|
||||||
#define MAXHIDDEN 128
|
#define MAXHIDDEN 128
|
||||||
|
|
47
event.c
47
event.c
|
@ -19,8 +19,9 @@
|
||||||
#include "patchlevel.h"
|
#include "patchlevel.h"
|
||||||
|
|
||||||
void mainloop(int shape_event) {
|
void mainloop(int shape_event) {
|
||||||
XEvent ev;
|
static XEvent ev;
|
||||||
int i;
|
static Client* c;
|
||||||
|
static int monitor;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
getevent(&ev);
|
getevent(&ev);
|
||||||
|
@ -43,15 +44,12 @@ void mainloop(int shape_event) {
|
||||||
case 89:
|
case 89:
|
||||||
if (XRRUpdateConfiguration(&ev)) {
|
if (XRRUpdateConfiguration(&ev)) {
|
||||||
fetchmonitorinfo();
|
fetchmonitorinfo();
|
||||||
fprintf(stderr, "%d monitors:\n", nmonitors);
|
monitor = getmonitorbyclient(c);
|
||||||
for (i = 0; i < nmonitors; i++) {
|
if (monitor < 0 || monitor >= nmonitors) {
|
||||||
fprintf(
|
break;
|
||||||
stderr,
|
}
|
||||||
" %d,%d,%d,%d\n",
|
for (c = clients; c; c = c->next) {
|
||||||
monitorinfo[i].x,
|
wrangle(c, monitorinfo[monitor]);
|
||||||
monitorinfo[i].y,
|
|
||||||
monitorinfo[i].width,
|
|
||||||
monitorinfo[i].height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -153,11 +151,6 @@ void configurereq(XConfigureRequestEvent* e) {
|
||||||
if (e->value_mask & CWBorderWidth)
|
if (e->value_mask & CWBorderWidth)
|
||||||
c->border = e->border_width;
|
c->border = e->border_width;
|
||||||
|
|
||||||
if (c->dx >= c->screen->width && c->dy >= c->screen->height)
|
|
||||||
c->border = 0;
|
|
||||||
else
|
|
||||||
c->border = BORDER;
|
|
||||||
|
|
||||||
if (e->value_mask & CWStackMode) {
|
if (e->value_mask & CWStackMode) {
|
||||||
if (e->detail == Above)
|
if (e->detail == Above)
|
||||||
top(c);
|
top(c);
|
||||||
|
@ -255,10 +248,13 @@ void mapreq(XMapRequestEvent* e) {
|
||||||
|
|
||||||
void unmap(XUnmapEvent* e) {
|
void unmap(XUnmapEvent* e) {
|
||||||
Client* c;
|
Client* c;
|
||||||
|
int monitor;
|
||||||
|
|
||||||
curtime = CurrentTime;
|
curtime = CurrentTime;
|
||||||
c = getclient(e->window, 0);
|
c = getclient(e->window, 0);
|
||||||
|
|
||||||
if (c) {
|
if (c) {
|
||||||
|
monitor = getmonitorbyclient(c);
|
||||||
switch (c->state) {
|
switch (c->state) {
|
||||||
case IconicState:
|
case IconicState:
|
||||||
if (e->send_event) {
|
if (e->send_event) {
|
||||||
|
@ -268,7 +264,7 @@ void unmap(XUnmapEvent* e) {
|
||||||
break;
|
break;
|
||||||
case NormalState:
|
case NormalState:
|
||||||
if (c == current)
|
if (c == current)
|
||||||
nofocus();
|
shuffleonmonitor(monitor);
|
||||||
if (!c->reparenting)
|
if (!c->reparenting)
|
||||||
withdraw(c);
|
withdraw(c);
|
||||||
break;
|
break;
|
||||||
|
@ -284,8 +280,9 @@ void circulatereq(XCirculateRequestEvent* e) {
|
||||||
void newwindow(XCreateWindowEvent* e) {
|
void newwindow(XCreateWindowEvent* e) {
|
||||||
Client* c;
|
Client* c;
|
||||||
ScreenInfo* s;
|
ScreenInfo* s;
|
||||||
static XWindowAttributes ra;
|
XRRMonitorInfo monitor;
|
||||||
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
|
||||||
|
monitor = monitorinfo[getmonitorbymouse()];
|
||||||
|
|
||||||
/* we don't set curtime as nothing here uses it */
|
/* we don't set curtime as nothing here uses it */
|
||||||
if (e->override_redirect)
|
if (e->override_redirect)
|
||||||
|
@ -330,9 +327,9 @@ void newwindow(XCreateWindowEvent* e) {
|
||||||
if (kbLaunch) {
|
if (kbLaunch) {
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
#ifdef CENTERVMAX
|
#ifdef CENTERVMAX
|
||||||
centerclient(c, ra, 1);
|
centerclient(c, monitor, 1);
|
||||||
#else
|
#else
|
||||||
centerclient(c, ra, 0);
|
centerclient(c, monitor, 0);
|
||||||
#endif
|
#endif
|
||||||
kbLaunch = 0;
|
kbLaunch = 0;
|
||||||
}
|
}
|
||||||
|
@ -341,21 +338,21 @@ void newwindow(XCreateWindowEvent* e) {
|
||||||
void destroy(Window w) {
|
void destroy(Window w) {
|
||||||
int i;
|
int i;
|
||||||
Client* c;
|
Client* c;
|
||||||
// int v;
|
int monitor;
|
||||||
|
|
||||||
curtime = CurrentTime;
|
curtime = CurrentTime;
|
||||||
c = getclient(w, 0);
|
c = getclient(w, 0);
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// v = c->virt;
|
monitor = getmonitorbyclient(c);
|
||||||
if (numvirtuals > 1)
|
if (numvirtuals > 1)
|
||||||
for (i = 0; i < numvirtuals; i++)
|
for (i = 0; i < numvirtuals; i++)
|
||||||
if (currents[i] == c)
|
if (currents[i] == c)
|
||||||
currents[i] = 0;
|
currents[i] = 0;
|
||||||
|
|
||||||
rmclient(c);
|
rmclient(c);
|
||||||
ensureactive();
|
ensureactiveonmonitor(monitor);
|
||||||
|
|
||||||
/* flush any errors generated by the window's sudden demise */
|
/* flush any errors generated by the window's sudden demise */
|
||||||
ignore_badwindow = 1;
|
ignore_badwindow = 1;
|
||||||
|
@ -372,7 +369,7 @@ void clientmesg(XClientMessageEvent* e) {
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
if (e->message_type == restart_rio) {
|
if (e->message_type == restart_rio) {
|
||||||
fprintf(stderr, "*** rio restarting ***\n");
|
fprintf(stderr, "*** ryudo restarting ***\n");
|
||||||
cleanup();
|
cleanup();
|
||||||
execvp(myargv[0], myargv);
|
execvp(myargv[0], myargv);
|
||||||
perror("ryudo: exec failed");
|
perror("ryudo: exec failed");
|
||||||
|
|
9
fns.h
9
fns.h
|
@ -65,9 +65,9 @@ void gettrans();
|
||||||
void keypress();
|
void keypress();
|
||||||
void keyrelease();
|
void keyrelease();
|
||||||
void keysetup();
|
void keysetup();
|
||||||
void quickreshape(Client*, int, int, int, int);
|
void quickreshape(Client*, int, int, int, int, int);
|
||||||
void stickystack(int);
|
void stickystack(int);
|
||||||
void centerclient(Client*, XWindowAttributes, int);
|
void centerclient(Client*, XRRMonitorInfo, int);
|
||||||
|
|
||||||
/* menu.c */
|
/* menu.c */
|
||||||
void button();
|
void button();
|
||||||
|
@ -101,6 +101,8 @@ int istransparent(Client* c);
|
||||||
int shouldalwaysdraw(Client* c);
|
int shouldalwaysdraw(Client* c);
|
||||||
int isterminalwindow(Client* c);
|
int isterminalwindow(Client* c);
|
||||||
void ensureactive();
|
void ensureactive();
|
||||||
|
void ensureactiveonmonitor(int);
|
||||||
|
void shuffleonmonitor(int);
|
||||||
|
|
||||||
/* grab.c */
|
/* grab.c */
|
||||||
int menuhit();
|
int menuhit();
|
||||||
|
@ -125,4 +127,5 @@ void ShowEvent(XEvent*);
|
||||||
|
|
||||||
void fetchmonitorinfo();
|
void fetchmonitorinfo();
|
||||||
int getmonitorbyclient(Client*);
|
int getmonitorbyclient(Client*);
|
||||||
int getmonitorbymouse();
|
int getmonitorbymouse();
|
||||||
|
void wrangle(Client*, XRRMonitorInfo);
|
||||||
|
|
1
grab.c
1
grab.c
|
@ -7,6 +7,7 @@
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
int nobuttons(XButtonEvent* e) /* Einstuerzende */
|
int nobuttons(XButtonEvent* e) /* Einstuerzende */
|
||||||
{
|
{
|
||||||
|
|
317
key.c
317
key.c
|
@ -53,6 +53,9 @@ void keysetup(void) {
|
||||||
#ifdef STICK_KEY
|
#ifdef STICK_KEY
|
||||||
int scode = XKeysymToKeycode(dpy, STICK_KEY);
|
int scode = XKeysymToKeycode(dpy, STICK_KEY);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
int acode = XKeysymToKeycode(dpy, WRANGLE_KEY);
|
||||||
|
#endif
|
||||||
#ifdef SNAPLEFT_KEY
|
#ifdef SNAPLEFT_KEY
|
||||||
int hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY);
|
int hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY);
|
||||||
#endif
|
#endif
|
||||||
|
@ -240,6 +243,42 @@ void keysetup(void) {
|
||||||
GrabModeSync,
|
GrabModeSync,
|
||||||
GrabModeAsync);
|
GrabModeAsync);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
XGrabKey(
|
||||||
|
dpy,
|
||||||
|
acode,
|
||||||
|
SHORTCUTMOD,
|
||||||
|
screens[i].root,
|
||||||
|
0,
|
||||||
|
GrabModeSync,
|
||||||
|
GrabModeAsync);
|
||||||
|
XGrabKey(
|
||||||
|
dpy,
|
||||||
|
acode,
|
||||||
|
SHORTCUTMOD | Mod2Mask,
|
||||||
|
screens[i].root,
|
||||||
|
0,
|
||||||
|
GrabModeSync,
|
||||||
|
GrabModeAsync);
|
||||||
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
XGrabKey(
|
||||||
|
dpy,
|
||||||
|
wcode,
|
||||||
|
SHORTCUTMOD,
|
||||||
|
screens[i].root,
|
||||||
|
0,
|
||||||
|
GrabModeSync,
|
||||||
|
GrabModeAsync);
|
||||||
|
XGrabKey(
|
||||||
|
dpy,
|
||||||
|
wcode,
|
||||||
|
SHORTCUTMOD | Mod2Mask,
|
||||||
|
screens[i].root,
|
||||||
|
0,
|
||||||
|
GrabModeSync,
|
||||||
|
GrabModeAsync);
|
||||||
|
#endif
|
||||||
#ifdef SNAPLEFT_KEY
|
#ifdef SNAPLEFT_KEY
|
||||||
XGrabKey(
|
XGrabKey(
|
||||||
dpy,
|
dpy,
|
||||||
|
@ -553,74 +592,150 @@ void keypress(XKeyEvent* e) {
|
||||||
/*
|
/*
|
||||||
* process key press here
|
* process key press here
|
||||||
*/
|
*/
|
||||||
int tabcode = XKeysymToKeycode(dpy, XK_Tab);
|
static int m;
|
||||||
|
static XRRMonitorInfo monitor;
|
||||||
|
|
||||||
|
static int tabcode;
|
||||||
#ifdef DESTROY_KEY
|
#ifdef DESTROY_KEY
|
||||||
int dcode = XKeysymToKeycode(dpy, DESTROY_KEY);
|
static int dcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ICON_KEY
|
#ifdef ICON_KEY
|
||||||
int icode = XKeysymToKeycode(dpy, ICON_KEY);
|
static int icode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef UNHIDE_KEY
|
#ifdef UNHIDE_KEY
|
||||||
int ucode = XKeysymToKeycode(dpy, UNHIDE_KEY);
|
static int ucode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MAX_KEY
|
#ifdef MAX_KEY
|
||||||
int mcode = XKeysymToKeycode(dpy, MAX_KEY);
|
static int mcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOVE_KEY
|
#ifdef MOVE_KEY
|
||||||
int vcode = XKeysymToKeycode(dpy, MOVE_KEY);
|
static int vcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef STICK_KEY
|
#ifdef STICK_KEY
|
||||||
int scode = XKeysymToKeycode(dpy, STICK_KEY);
|
static int scode;
|
||||||
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
static int acode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef RESIZE_KEY
|
#ifdef RESIZE_KEY
|
||||||
int rcode = XKeysymToKeycode(dpy, RESIZE_KEY);
|
static int rcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef LAUNCH_KEY
|
#ifdef LAUNCH_KEY
|
||||||
int slcode = XKeysymToKeycode(dpy, LAUNCH_KEY);
|
static int slcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ZOOM_KEY
|
#ifdef ZOOM_KEY
|
||||||
int zcode = XKeysymToKeycode(dpy, ZOOM_KEY);
|
static int zcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPLEFT_KEY
|
#ifdef SNAPLEFT_KEY
|
||||||
int hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY);
|
static int hcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPRIGHT_KEY
|
#ifdef SNAPRIGHT_KEY
|
||||||
int lcode = XKeysymToKeycode(dpy, SNAPRIGHT_KEY);
|
static int lcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOM_KEY
|
#ifdef SNAPBOTTOM_KEY
|
||||||
int jcode = XKeysymToKeycode(dpy, SNAPBOTTOM_KEY);
|
static int jcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPTOP_KEY
|
#ifdef SNAPTOP_KEY
|
||||||
int kcode = XKeysymToKeycode(dpy, SNAPTOP_KEY);
|
int kcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPTOPLEFT_KEY
|
#ifdef SNAPTOPLEFT_KEY
|
||||||
int qcode = XKeysymToKeycode(dpy, SNAPTOPLEFT_KEY);
|
static int qcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOMLEFT_KEY
|
#ifdef SNAPBOTTOMLEFT_KEY
|
||||||
int wcode = XKeysymToKeycode(dpy, SNAPBOTTOMLEFT_KEY);
|
static int wcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOMRIGHT_KEY
|
#ifdef SNAPBOTTOMRIGHT_KEY
|
||||||
int ocode = XKeysymToKeycode(dpy, SNAPBOTTOMRIGHT_KEY);
|
static int ocode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPTOPRIGHT_KEY
|
#ifdef SNAPTOPRIGHT_KEY
|
||||||
int pcode = XKeysymToKeycode(dpy, SNAPTOPRIGHT_KEY);
|
static int pcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPCENTER_KEY
|
#ifdef SNAPCENTER_KEY
|
||||||
int ccode = XKeysymToKeycode(dpy, SNAPCENTER_KEY);
|
static int ccode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef NEXTVIRT_KEY
|
#ifdef NEXTVIRT_KEY
|
||||||
int rightcode = XKeysymToKeycode(dpy, NEXTVIRT_KEY);
|
static int rightcode;
|
||||||
#endif
|
#endif
|
||||||
#ifdef PREVVIRT_KEY
|
#ifdef PREVVIRT_KEY
|
||||||
int leftcode = XKeysymToKeycode(dpy, PREVVIRT_KEY);
|
static int leftcode;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tabcode = XKeysymToKeycode(dpy, XK_Tab);
|
||||||
|
#ifdef DESTROY_KEY
|
||||||
|
dcode = XKeysymToKeycode(dpy, DESTROY_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef ICON_KEY
|
||||||
|
icode = XKeysymToKeycode(dpy, ICON_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef UNHIDE_KEY
|
||||||
|
ucode = XKeysymToKeycode(dpy, UNHIDE_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef MAX_KEY
|
||||||
|
mcode = XKeysymToKeycode(dpy, MAX_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef MOVE_KEY
|
||||||
|
vcode = XKeysymToKeycode(dpy, MOVE_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef STICK_KEY
|
||||||
|
scode = XKeysymToKeycode(dpy, STICK_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
wcode = XKeysymToKeycode(dpy, WRANGLE_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef RESIZE_KEY
|
||||||
|
rcode = XKeysymToKeycode(dpy, RESIZE_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef LAUNCH_KEY
|
||||||
|
slcode = XKeysymToKeycode(dpy, LAUNCH_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef ZOOM_KEY
|
||||||
|
zcode = XKeysymToKeycode(dpy, ZOOM_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPLEFT_KEY
|
||||||
|
hcode = XKeysymToKeycode(dpy, SNAPLEFT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPRIGHT_KEY
|
||||||
|
lcode = XKeysymToKeycode(dpy, SNAPRIGHT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPBOTTOM_KEY
|
||||||
|
jcode = XKeysymToKeycode(dpy, SNAPBOTTOM_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPTOP_KEY
|
||||||
|
kcode = XKeysymToKeycode(dpy, SNAPTOP_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPTOPLEFT_KEY
|
||||||
|
qcode = XKeysymToKeycode(dpy, SNAPTOPLEFT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPBOTTOMLEFT_KEY
|
||||||
|
wcode = XKeysymToKeycode(dpy, SNAPBOTTOMLEFT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPBOTTOMRIGHT_KEY
|
||||||
|
ocode = XKeysymToKeycode(dpy, SNAPBOTTOMRIGHT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPTOPRIGHT_KEY
|
||||||
|
pcode = XKeysymToKeycode(dpy, SNAPTOPRIGHT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef SNAPCENTER_KEY
|
||||||
|
ccode = XKeysymToKeycode(dpy, SNAPCENTER_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef NEXTVIRT_KEY
|
||||||
|
rightcode = XKeysymToKeycode(dpy, NEXTVIRT_KEY);
|
||||||
|
#endif
|
||||||
|
#ifdef PREVVIRT_KEY
|
||||||
|
leftcode = XKeysymToKeycode(dpy, PREVVIRT_KEY);
|
||||||
#endif
|
#endif
|
||||||
#ifdef DEVEL
|
#ifdef DEVEL
|
||||||
int tcode = XKeysymToKeycode(dpy, STICKYTOFRONT_KEY);
|
int tcode = XKeysymToKeycode(dpy, STICKYTOFRONT_KEY);
|
||||||
int bcode = XKeysymToKeycode(dpy, STICKYTOBACK_KEY);
|
int bcode = XKeysymToKeycode(dpy, STICKYTOBACK_KEY);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static XWindowAttributes ra;
|
#ifdef MONITORFOLLOWSMOUSE
|
||||||
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
m = current ? getmonitorbyclient(current) : getmonitorbymouse();
|
||||||
|
#else
|
||||||
|
m = getmonitorbyclient(current);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
monitor = monitorinfo[m];
|
||||||
|
|
||||||
/* basic wm functionality */
|
/* basic wm functionality */
|
||||||
if (e->keycode == tabcode && (e->state & Mod1Mask) == (1 << 3))
|
if (e->keycode == tabcode && (e->state & Mod1Mask) == (1 << 3))
|
||||||
|
@ -649,15 +764,22 @@ void keypress(XKeyEvent* e) {
|
||||||
else if (e->keycode == mcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == mcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
-BORDER,
|
monitor.x,
|
||||||
-BORDER,
|
monitor.y,
|
||||||
ra.width + 2 * BORDER,
|
monitor.width,
|
||||||
ra.height + 2 * BORDER);
|
monitor.height,
|
||||||
|
1);
|
||||||
#endif
|
#endif
|
||||||
#ifdef STICK_KEY
|
#ifdef STICK_KEY
|
||||||
else if (e->keycode == scode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == scode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
stick(current);
|
stick(current);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WRANGLE_KEY
|
||||||
|
else if (e->keycode == acode && (e->state & SHORTCUTMOD) == (MODBITS)) {
|
||||||
|
wrangle(current, m < nmonitors - 1 ? monitorinfo[m++] : monitorinfo[0]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ZOOM_KEY
|
#ifdef ZOOM_KEY
|
||||||
else if (e->keycode == zcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == zcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
zoom = !zoom;
|
zoom = !zoom;
|
||||||
|
@ -668,10 +790,11 @@ void keypress(XKeyEvent* e) {
|
||||||
if (zoom) {
|
if (zoom) {
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
-BORDER,
|
monitor.x,
|
||||||
-BORDER,
|
monitor.y,
|
||||||
ra.width + 2 * BORDER,
|
monitor.width,
|
||||||
ra.height + 2 * BORDER);
|
monitor.height,
|
||||||
|
1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -681,37 +804,41 @@ void keypress(XKeyEvent* e) {
|
||||||
else if (e->keycode == hcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == hcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
GAPSZ,
|
monitor.x + GAPSZ,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height - 2 * GAPSZ);
|
monitor.height - 2 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPRIGHT_KEY
|
#ifdef SNAPRIGHT_KEY
|
||||||
else if (e->keycode == lcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == lcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
ra.width / 2 + 0.5 * GAPSZ,
|
monitor.x + monitor.width / 2 + 0.5 * GAPSZ,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height - 2 * GAPSZ);
|
monitor.height - 2 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOM_KEY
|
#ifdef SNAPBOTTOM_KEY
|
||||||
else if (e->keycode == jcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == jcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
GAPSZ,
|
monitor.x + GAPSZ,
|
||||||
ra.height / 2 + 0.5 * GAPSZ,
|
monitor.y + monitor.height / 2 + 0.5 * GAPSZ,
|
||||||
ra.width - 2 * GAPSZ,
|
monitor.width - 2 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPTOP_KEY
|
#ifdef SNAPTOP_KEY
|
||||||
else if (e->keycode == kcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == kcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
GAPSZ,
|
monitor.x + GAPSZ,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
ra.width - 2 * GAPSZ,
|
monitor.width - 2 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* quarter snap */
|
/* quarter snap */
|
||||||
|
@ -719,37 +846,41 @@ void keypress(XKeyEvent* e) {
|
||||||
else if (e->keycode == qcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == qcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
GAPSZ,
|
monitor.x + GAPSZ,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOMLEFT_KEY
|
#ifdef SNAPBOTTOMLEFT_KEY
|
||||||
else if (e->keycode == wcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == wcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
GAPSZ,
|
monitor.x + GAPSZ,
|
||||||
ra.height / 2 + 0.5 * GAPSZ,
|
monitor.y + monitor.height / 2 + 0.5 * GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPBOTTOMRIGHT_KEY
|
#ifdef SNAPBOTTOMRIGHT_KEY
|
||||||
else if (e->keycode == ocode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == ocode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
ra.width / 2 + 0.5 * GAPSZ,
|
monitor.x + monitor.width / 2 + 0.5 * GAPSZ,
|
||||||
ra.height / 2 + 0.5 * GAPSZ,
|
monitor.y + monitor.height / 2 + 0.5 * GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
#ifdef SNAPTOPRIGHT_KEY
|
#ifdef SNAPTOPRIGHT_KEY
|
||||||
else if (e->keycode == pcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
else if (e->keycode == pcode && (e->state & SHORTCUTMOD) == (MODBITS))
|
||||||
quickreshape(
|
quickreshape(
|
||||||
current,
|
current,
|
||||||
ra.width / 2 + 0.5 * GAPSZ,
|
monitor.x + monitor.width / 2 + 0.5 * GAPSZ,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
ra.width / 2 - 1.5 * GAPSZ,
|
monitor.width / 2 - 1.5 * GAPSZ,
|
||||||
ra.height / 2 - 1.5 * GAPSZ);
|
monitor.height / 2 - 1.5 * GAPSZ,
|
||||||
|
0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* center snap */
|
/* center snap */
|
||||||
|
@ -757,15 +888,15 @@ void keypress(XKeyEvent* e) {
|
||||||
else if (e->keycode == ccode && (e->state & SHORTCUTMOD) == (MODBITS)) {
|
else if (e->keycode == ccode && (e->state & SHORTCUTMOD) == (MODBITS)) {
|
||||||
if ((e->state & ShiftMask) == (1 << 0)) {
|
if ((e->state & ShiftMask) == (1 << 0)) {
|
||||||
#ifdef CENTERVMAX
|
#ifdef CENTERVMAX
|
||||||
centerclient(current, ra, 0);
|
centerclient(current, monitor, 0);
|
||||||
#else
|
#else
|
||||||
centerclient(current, ra, 1);
|
centerclient(current, monitor, 1);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef CENTERVMAX
|
#ifdef CENTERVMAX
|
||||||
centerclient(current, ra, 1);
|
centerclient(current, monitor, 1);
|
||||||
#else
|
#else
|
||||||
centerclient(current, ra, 0);
|
centerclient(current, monitor, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,19 +966,24 @@ void keypress(XKeyEvent* e) {
|
||||||
|
|
||||||
void keyrelease(XKeyEvent* e) { XAllowEvents(dpy, SyncKeyboard, e->time); }
|
void keyrelease(XKeyEvent* e) { XAllowEvents(dpy, SyncKeyboard, e->time); }
|
||||||
|
|
||||||
void quickreshape(Client* c, int x, int y, int dx, int dy) {
|
void quickreshape(Client* c, int x, int y, int dx, int dy, int max) {
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
return;
|
return;
|
||||||
XMoveResizeWindow(dpy, c->parent, x, y, dx, dy);
|
XMoveResizeWindow(dpy, c->parent, x, y, dx, dy);
|
||||||
c->x = x + BORDER;
|
if (max)
|
||||||
c->y = y + BORDER;
|
c->border = 0;
|
||||||
c->dx = dx - 2 * BORDER;
|
else
|
||||||
c->dy = dy - 2 * BORDER;
|
c->border = BORDER;
|
||||||
XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
|
|
||||||
|
c->x = x + c->border;
|
||||||
|
c->y = y + c->border;
|
||||||
|
c->dx = dx - 2 * c->border;
|
||||||
|
c->dy = dy - 2 * c->border;
|
||||||
|
XMoveResizeWindow(dpy, c->window, c->border, c->border, c->dx, c->dy);
|
||||||
sendconfig(c);
|
sendconfig(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void centerclient(Client* c, XWindowAttributes ra, int vmax) {
|
void centerclient(Client* c, XRRMonitorInfo monitor, int vmax) {
|
||||||
static int centeroffsetnum =
|
static int centeroffsetnum =
|
||||||
CENTERNUM % 2 == 0 ? CENTERDEN - CENTERNUM : (CENTERDEN - CENTERNUM) / 2;
|
CENTERNUM % 2 == 0 ? CENTERDEN - CENTERNUM : (CENTERDEN - CENTERNUM) / 2;
|
||||||
|
|
||||||
|
@ -856,23 +992,36 @@ void centerclient(Client* c, XWindowAttributes ra, int vmax) {
|
||||||
if (vmax) {
|
if (vmax) {
|
||||||
quickreshape(
|
quickreshape(
|
||||||
c,
|
c,
|
||||||
centeroffsetnum * ra.width / centeroffsetden,
|
monitor.x + centeroffsetnum * monitor.width / centeroffsetden,
|
||||||
GAPSZ,
|
monitor.y + GAPSZ,
|
||||||
CENTERNUM * ra.width / CENTERDEN,
|
CENTERNUM * monitor.width / CENTERDEN,
|
||||||
ra.height - 2 * GAPSZ);
|
monitor.height - 2 * GAPSZ,
|
||||||
|
0);
|
||||||
} else {
|
} else {
|
||||||
quickreshape(
|
quickreshape(
|
||||||
c,
|
c,
|
||||||
centeroffsetnum * ra.width / centeroffsetden,
|
monitor.x + centeroffsetnum * monitor.width / centeroffsetden,
|
||||||
centeroffsetnum * ra.height / centeroffsetden,
|
monitor.y + centeroffsetnum * monitor.height / centeroffsetden,
|
||||||
CENTERNUM * ra.width / CENTERDEN,
|
CENTERNUM * monitor.width / CENTERDEN,
|
||||||
CENTERNUM * ra.height / CENTERDEN);
|
CENTERNUM * monitor.height / CENTERDEN,
|
||||||
|
0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void alttab(int shift) {
|
static void alttab(int shift) {
|
||||||
shuffle(shift);
|
static int monitor;
|
||||||
/* fprintf(stderr, "%sTab\n", shift ? "Back" : ""); */
|
|
||||||
|
if (!shift) {
|
||||||
|
shuffle(0);
|
||||||
|
} else {
|
||||||
|
monitor = getmonitorbyclient(current);
|
||||||
|
if (monitor == nmonitors - 1) {
|
||||||
|
monitor = 0;
|
||||||
|
} else {
|
||||||
|
monitor++;
|
||||||
|
}
|
||||||
|
shuffleonmonitor(monitor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEVEL
|
#ifdef DEVEL
|
||||||
|
|
13
main.c
13
main.c
|
@ -22,7 +22,7 @@
|
||||||
#include "patchlevel.h"
|
#include "patchlevel.h"
|
||||||
|
|
||||||
char* version[] = {
|
char* version[] = {
|
||||||
"ryudo version 1.2.2\nCopyright (c) 1994-1996 David Hogan,\n(c) 2004 Russ "
|
"ryudo version 1.3.0\nCopyright (c) 1994-1996 David Hogan,\n(c) 2004 Russ "
|
||||||
"Cox,\n(c) 2019-2022 Derek Stevens",
|
"Cox,\n(c) 2019-2022 Derek Stevens",
|
||||||
0};
|
0};
|
||||||
|
|
||||||
|
@ -30,14 +30,11 @@ Display* dpy;
|
||||||
ScreenInfo* screens;
|
ScreenInfo* screens;
|
||||||
int initting;
|
int initting;
|
||||||
XFontStruct* font;
|
XFontStruct* font;
|
||||||
int nostalgia;
|
|
||||||
char** myargv;
|
char** myargv;
|
||||||
char* termprog;
|
char* termprog;
|
||||||
char* shell;
|
char* shell;
|
||||||
Bool shape;
|
Bool shape;
|
||||||
int _border = 4;
|
|
||||||
int _corner = 25;
|
int _corner = 25;
|
||||||
int _inset = 1;
|
|
||||||
int curtime;
|
int curtime;
|
||||||
int debug;
|
int debug;
|
||||||
int signalled;
|
int signalled;
|
||||||
|
@ -88,9 +85,7 @@ int main(int argc, char* argv[]) {
|
||||||
font = 0;
|
font = 0;
|
||||||
fname = 0;
|
fname = 0;
|
||||||
for (i = 1; i < argc; i++)
|
for (i = 1; i < argc; i++)
|
||||||
if (strcmp(argv[i], "-nostalgia") == 0)
|
if (strcmp(argv[i], "-debug") == 0)
|
||||||
nostalgia++;
|
|
||||||
else if (strcmp(argv[i], "-debug") == 0)
|
|
||||||
debug++;
|
debug++;
|
||||||
|
|
||||||
else if (strcmp(argv[i], "-ffm") == 0)
|
else if (strcmp(argv[i], "-ffm") == 0)
|
||||||
|
@ -196,10 +191,6 @@ int main(int argc, char* argv[]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nostalgia) {
|
|
||||||
_border--;
|
|
||||||
_inset--;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SHAPE
|
#ifdef SHAPE
|
||||||
shape = XShapeQueryExtension(dpy, &shape_event, &dummy);
|
shape = XShapeQueryExtension(dpy, &shape_event, &dummy);
|
||||||
|
|
50
manage.c
50
manage.c
|
@ -29,6 +29,7 @@ int manage(Client* c, int mapped) {
|
||||||
XClassHint class;
|
XClassHint class;
|
||||||
XWMHints* hints;
|
XWMHints* hints;
|
||||||
XSetWindowAttributes attrs;
|
XSetWindowAttributes attrs;
|
||||||
|
XRRMonitorInfo monitor;
|
||||||
|
|
||||||
static XWindowAttributes ra;
|
static XWindowAttributes ra;
|
||||||
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
||||||
|
@ -223,49 +224,18 @@ int manage(Client* c, int mapped) {
|
||||||
|
|
||||||
/* If the window is out of bounds of the screen, try to wrangle it */
|
/* If the window is out of bounds of the screen, try to wrangle it */
|
||||||
|
|
||||||
/* If it's bigger than the screen, try to set it maximized */
|
if (c->trans) {
|
||||||
if (c->dx >= ra.width || c->dy >= ra.width) {
|
monitor = monitorinfo[getmonitorbyclient(c)];
|
||||||
if (c->dx >= ra.width)
|
|
||||||
quickreshape(
|
|
||||||
c,
|
|
||||||
-BORDER,
|
|
||||||
c->y - BORDER,
|
|
||||||
ra.width + 2 * BORDER,
|
|
||||||
c->dy + 2 * BORDER);
|
|
||||||
if (c->dy >= ra.height)
|
|
||||||
quickreshape(
|
|
||||||
c,
|
|
||||||
c->x - BORDER,
|
|
||||||
-BORDER,
|
|
||||||
c->dx + 2 * BORDER,
|
|
||||||
ra.height + 2 * BORDER);
|
|
||||||
|
|
||||||
/* and if it's got an edge out of bounds, nudge it into bounds */
|
|
||||||
} else {
|
} else {
|
||||||
if (c->x < BORDER) {
|
#ifdef MONITORFOLLOWSMOUSE
|
||||||
quickreshape(c, 0, c->y - BORDER, c->dx + 2 * BORDER, c->dy + 2 * BORDER);
|
monitor = monitorinfo[getmonitorbymouse()];
|
||||||
}
|
#else
|
||||||
if (c->y < BORDER) {
|
monitor = monitorinfo[getmonitorbyclient(current)];
|
||||||
quickreshape(c, c->x - BORDER, 0, c->dx + 2 * BORDER, c->dy + 2 * BORDER);
|
#endif
|
||||||
}
|
|
||||||
if (c->x + c->dx + BORDER > ra.width) {
|
|
||||||
quickreshape(
|
|
||||||
c,
|
|
||||||
ra.width - (c->dx + 2 * BORDER),
|
|
||||||
c->y - BORDER,
|
|
||||||
c->dx + 2 * BORDER,
|
|
||||||
c->dy + 2 * BORDER);
|
|
||||||
}
|
|
||||||
if (c->y + c->dy + BORDER > ra.height) {
|
|
||||||
quickreshape(
|
|
||||||
c,
|
|
||||||
c->x - BORDER,
|
|
||||||
ra.height - (c->dy + 2 * BORDER),
|
|
||||||
c->dx + 2 * BORDER,
|
|
||||||
c->dy + 2 * BORDER);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wrangle(c, monitor);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we swept the window, let's send a resize event to the
|
* If we swept the window, let's send a resize event to the
|
||||||
* guy who just got resized. It's not clear whether the apps
|
* guy who just got resized. It's not clear whether the apps
|
||||||
|
|
29
menu.c
29
menu.c
|
@ -83,8 +83,9 @@ void button(XButtonEvent* e) {
|
||||||
Window dw;
|
Window dw;
|
||||||
ScreenInfo* s;
|
ScreenInfo* s;
|
||||||
|
|
||||||
static XWindowAttributes ra;
|
#ifdef SHOWMAX
|
||||||
XGetWindowAttributes(dpy, DefaultRootWindow(dpy), &ra);
|
XRRMonitorInfo monitor;
|
||||||
|
#endif
|
||||||
|
|
||||||
curtime = e->time;
|
curtime = e->time;
|
||||||
s = getscreen(e->root);
|
s = getscreen(e->root);
|
||||||
|
@ -210,12 +211,8 @@ void button(XButtonEvent* e) {
|
||||||
if (isautostick(c))
|
if (isautostick(c))
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
quickreshape(
|
monitor = monitorinfo[getmonitorbyclient(c)];
|
||||||
c,
|
quickreshape(c, monitor.x, monitor.y, monitor.width, monitor.height, 1);
|
||||||
-BORDER,
|
|
||||||
-BORDER,
|
|
||||||
ra.width + 2 * BORDER,
|
|
||||||
ra.height + 2 * BORDER);
|
|
||||||
active(c);
|
active(c);
|
||||||
top(c);
|
top(c);
|
||||||
break;
|
break;
|
||||||
|
@ -281,6 +278,8 @@ void reshape(
|
||||||
ody = c->dy;
|
ody = c->dy;
|
||||||
if (fn(c, but, e) == 0)
|
if (fn(c, but, e) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
c->border = BORDER;
|
||||||
active(c);
|
active(c);
|
||||||
top(c);
|
top(c);
|
||||||
XRaiseWindow(dpy, c->parent);
|
XRaiseWindow(dpy, c->parent);
|
||||||
|
@ -302,10 +301,11 @@ void move(Client* c, int but) {
|
||||||
return;
|
return;
|
||||||
if (drag(c, but) == 0)
|
if (drag(c, but) == 0)
|
||||||
return;
|
return;
|
||||||
|
c->border = BORDER;
|
||||||
active(c);
|
active(c);
|
||||||
top(c);
|
top(c);
|
||||||
XRaiseWindow(dpy, c->parent);
|
XRaiseWindow(dpy, c->parent);
|
||||||
XMoveWindow(dpy, c->parent, c->x - BORDER, c->y - BORDER);
|
XMoveWindow(dpy, c->parent, c->x - c->border, c->y - c->border);
|
||||||
sendconfig(c);
|
sendconfig(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,7 +449,7 @@ void switch_to_c(int n, Client* c) {
|
||||||
XUnmapWindow(dpy, c->window);
|
XUnmapWindow(dpy, c->window);
|
||||||
setstate(c, IconicState);
|
setstate(c, IconicState);
|
||||||
if (c == current)
|
if (c == current)
|
||||||
nofocus();
|
setactive(c, 0);
|
||||||
} else if (c->virt == virt && c->state == IconicState) {
|
} else if (c->virt == virt && c->state == IconicState) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -463,6 +463,8 @@ void switch_to_c(int n, Client* c) {
|
||||||
setstate(c, NormalState);
|
setstate(c, NormalState);
|
||||||
if (currents[virt] == c)
|
if (currents[virt] == c)
|
||||||
active(c);
|
active(c);
|
||||||
|
else
|
||||||
|
setactive(c, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -476,6 +478,10 @@ void switch_to(int n) {
|
||||||
if (n == virt)
|
if (n == virt)
|
||||||
return;
|
return;
|
||||||
currents[virt] = current;
|
currents[virt] = current;
|
||||||
|
// if current is sticky, and no current in next virt, keep this one
|
||||||
|
if (current && current->virt == -1 && !currents[n]) {
|
||||||
|
currents[n] = current;
|
||||||
|
}
|
||||||
virt = n;
|
virt = n;
|
||||||
|
|
||||||
/* redundant when called from a menu switch
|
/* redundant when called from a menu switch
|
||||||
|
@ -484,9 +490,12 @@ void switch_to(int n) {
|
||||||
b2menu.lasthit = n;
|
b2menu.lasthit = n;
|
||||||
|
|
||||||
switch_to_c(n, clients);
|
switch_to_c(n, clients);
|
||||||
|
|
||||||
current = currents[virt];
|
current = currents[virt];
|
||||||
ensureactive();
|
ensureactive();
|
||||||
|
active(current);
|
||||||
top(current);
|
top(current);
|
||||||
|
|
||||||
#ifdef VIRTNOTIFY
|
#ifdef VIRTNOTIFY
|
||||||
sprintf(virtmsg, VIRTMSG, b2items[virt]);
|
sprintf(virtmsg, VIRTMSG, b2items[virt]);
|
||||||
notify_notification_update(notification, VIRTHEADER, virtmsg, NULL);
|
notify_notification_update(notification, VIRTHEADER, virtmsg, NULL);
|
||||||
|
|
68
monitor.c
68
monitor.c
|
@ -4,6 +4,7 @@
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include "dat.h"
|
#include "dat.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
int nmonitors = 0;
|
int nmonitors = 0;
|
||||||
XRRMonitorInfo* monitorinfo;
|
XRRMonitorInfo* monitorinfo;
|
||||||
|
@ -18,14 +19,21 @@ void fetchmonitorinfo() {
|
||||||
int getmonitorbyclient(Client* c) {
|
int getmonitorbyclient(Client* c) {
|
||||||
XRRMonitorInfo m;
|
XRRMonitorInfo m;
|
||||||
int cx, cy, i, p;
|
int cx, cy, i, p;
|
||||||
cx = c->x + c->dx / 2;
|
cx = cy = 0;
|
||||||
cy = c->y + c->dy / 2;
|
|
||||||
|
/* we check which monitor the center of the window is in */
|
||||||
|
if (c) {
|
||||||
|
cx = c->x + c->dx / 2;
|
||||||
|
cy = c->y + c->dy / 2;
|
||||||
|
}
|
||||||
|
|
||||||
p = 0;
|
p = 0;
|
||||||
|
|
||||||
for (i = 0; i < nmonitors; i++) {
|
for (i = 0; i < nmonitors; i++) {
|
||||||
m = monitorinfo[i];
|
m = monitorinfo[i];
|
||||||
if (cx >= m.x && cx < m.x + m.width && cy >= m.y && cy < m.y + m.height) {
|
if (
|
||||||
|
c && cx >= m.x && cx < m.x + m.width && cy >= m.y &&
|
||||||
|
cy < m.y + m.height) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +42,7 @@ int getmonitorbyclient(Client* c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if center is not within any window, return primary */
|
/* if center is not within any monitor, return primary */
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,4 +61,54 @@ int getmonitorbymouse() {
|
||||||
}
|
}
|
||||||
/* should never reach here, but return first monitor if we do */
|
/* should never reach here, but return first monitor if we do */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wrangle(Client* c, XRRMonitorInfo monitor) {
|
||||||
|
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* If it's bigger than the screen, try to set it maximized */
|
||||||
|
|
||||||
|
if (c->dx >= monitor.width && c->dy >= monitor.height) {
|
||||||
|
quickreshape(c, monitor.x, monitor.y, monitor.width, monitor.height, 1);
|
||||||
|
/* and if it's got an edge out of bounds, nudge it into bounds */
|
||||||
|
} else {
|
||||||
|
if (c->x < monitor.x + BORDER) {
|
||||||
|
quickreshape(
|
||||||
|
c,
|
||||||
|
monitor.x,
|
||||||
|
c->y - BORDER,
|
||||||
|
c->dx + 2 * BORDER,
|
||||||
|
c->dy + 2 * BORDER,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
if (c->y < monitor.y + BORDER) {
|
||||||
|
quickreshape(
|
||||||
|
c,
|
||||||
|
c->x - BORDER,
|
||||||
|
monitor.y,
|
||||||
|
c->dx + 2 * BORDER,
|
||||||
|
c->dy + 2 * BORDER,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
if (c->x + c->dx + BORDER > monitor.x + monitor.width) {
|
||||||
|
quickreshape(
|
||||||
|
c,
|
||||||
|
monitor.x + monitor.width - (c->dx + 2 * BORDER),
|
||||||
|
c->y - BORDER,
|
||||||
|
c->dx + 2 * BORDER,
|
||||||
|
c->dy + 2 * BORDER,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
if (c->y + c->dy + BORDER > monitor.y + monitor.height) {
|
||||||
|
quickreshape(
|
||||||
|
c,
|
||||||
|
c->x - BORDER,
|
||||||
|
monitor.y + monitor.height - (c->dy + 2 * BORDER),
|
||||||
|
c->dx + 2 * BORDER,
|
||||||
|
c->dy + 2 * BORDER,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
39
ryudo.1
39
ryudo.1
|
@ -1,4 +1,7 @@
|
||||||
.TH "RYUDO" "1" "November 2021" "" ""
|
.\" generated with Ronn/v0.7.3
|
||||||
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||||
|
.
|
||||||
|
.TH "RYUDO" "1" "February 2022" "" ""
|
||||||
.
|
.
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
\fBryudo\fR \- The floatiling window manager that flows
|
\fBryudo\fR \- The floatiling window manager that flows
|
||||||
|
@ -31,7 +34,29 @@ If either \fBexit\fR or \fBrestart\fR is given, the appropriate message is sent
|
||||||
Run the provided \fBbuild\.sh\fR and \fBinstall\.sh\fR scripts to build and install \fBryudo\fR\. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the \fBstartryudo\fR session wrapper to \fB/usr/bin/\fR and a \fB\.desktop\fR file to \fB/usr/share/xsessions/\fR If run as a regular user, they will install the program to \fB~/bin/9/\fR and not install the manual pages, wrapper, or \fB\.desktop\fR file\.
|
Run the provided \fBbuild\.sh\fR and \fBinstall\.sh\fR scripts to build and install \fBryudo\fR\. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the \fBstartryudo\fR session wrapper to \fB/usr/bin/\fR and a \fB\.desktop\fR file to \fB/usr/share/xsessions/\fR If run as a regular user, they will install the program to \fB~/bin/9/\fR and not install the manual pages, wrapper, or \fB\.desktop\fR file\.
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
Building requires \fBplan9port\fR and the \fBlibX11\fR and \fBlibXT\fR headers\. Optionally, \fBlibnotify\fR is used to show notifications when switching virtual desktops\.
|
Running and building require the following:
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
a full \fBplan9port\fR installation
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
\fBlibX11\fR and development headers
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
\fBlibXT\fR and development headers
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
\fBlibXrandr\fR and development headers
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
If virtual desktop switching notification is enabled, it requires
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
\fBlibnotify\fR and development headers
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
.
|
.
|
||||||
.SH "CONFIGURATION"
|
.SH "CONFIGURATION"
|
||||||
Many configuration options have been enabled as compile\-time options configured in the \fBconfig\.h\fR configuration file\. The \fBconfig\.def\.h\fR file shipped with the source code documents all of the options and contains what I hope are sane defaults\. If \fBconfig\.h\fR does not exist in the source directory, it will be copied from \fBconfig\.def\.h\fR on build\. After changing the configuration file, it is necessary to run the \fBbuild\.sh\fR and/or \fBinstall\.sh\fR script again and restart the program\.
|
Many configuration options have been enabled as compile\-time options configured in the \fBconfig\.h\fR configuration file\. The \fBconfig\.def\.h\fR file shipped with the source code documents all of the options and contains what I hope are sane defaults\. If \fBconfig\.h\fR does not exist in the source directory, it will be copied from \fBconfig\.def\.h\fR on build\. After changing the configuration file, it is necessary to run the \fBbuild\.sh\fR and/or \fBinstall\.sh\fR script again and restart the program\.
|
||||||
|
@ -81,6 +106,9 @@ Mouse button 1 focuses a window\. The click is not transferred to the window (yo
|
||||||
Alt\-Tab cycles focus through all windows on the current desktop\.
|
Alt\-Tab cycles focus through all windows on the current desktop\.
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
|
Multimonitor support via \fBXrandr(3)\fR is supported; keybinds should properly interpret the monitor the current window occupies (for \fBTile\-\fR, \fBMaximize\fR, etc) or the monitor the cursor is on (\fBLaunch\fR)
|
||||||
|
.
|
||||||
|
.P
|
||||||
The following operations are bindable to key combinations (shown are the default bindings):
|
The following operations are bindable to key combinations (shown are the default bindings):
|
||||||
.
|
.
|
||||||
.IP "\(bu" 4
|
.IP "\(bu" 4
|
||||||
|
@ -143,16 +171,13 @@ The following operations are bindable to key combinations (shown are the default
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
.
|
.
|
||||||
.SH "BUGS AND CAVEATS"
|
.SH "BUGS AND CAVEATS"
|
||||||
Multimonitor output is not currently supported \-\- the whole "screen" (collection of active monitors) is treated as one monitor, and keybinds and automatic window placement will not work properly\.
|
|
||||||
.
|
|
||||||
.P
|
|
||||||
Click events don\'t pass through when clicking to activate a window\.
|
Click events don\'t pass through when clicking to activate a window\.
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window\. I personally sometimes find this behavior useful\.
|
Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window\. I personally sometimes find this behavior useful\.
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at\. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so\.
|
Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at\. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so\. If the program expects to run at the current screen resolution, the window\-wrangling heuristics should maximize it and you\'ll be golden\. If the window is in override\-redirect mode, it should just run fullscreen without a hitch\.
|
||||||
.
|
.
|
||||||
.P
|
.P
|
||||||
Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset\. Maximize the window after opening and it should be good\.
|
Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset\. Maximize the window after opening and it should be good\.
|
||||||
|
@ -174,4 +199,4 @@ David Hogan, RIP
|
||||||
.IP "" 0
|
.IP "" 0
|
||||||
.
|
.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
rio(1), 9term(1)
|
rio(1), 9term(1), xrandr(1), Xrandr(3)
|
||||||
|
|
31
ryudo.1.html
31
ryudo.1.html
|
@ -99,7 +99,22 @@
|
||||||
|
|
||||||
<p>Run the provided <code>build.sh</code> and <code>install.sh</code> scripts to build and install <code>ryudo</code>. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the <code>startryudo</code> session wrapper to <code>/usr/bin/</code> and a <code>.desktop</code> file to <code>/usr/share/xsessions/</code> If run as a regular user, they will install the program to <code>~/bin/9/</code> and not install the manual pages, wrapper, or <code>.desktop</code> file.</p>
|
<p>Run the provided <code>build.sh</code> and <code>install.sh</code> scripts to build and install <code>ryudo</code>. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the <code>startryudo</code> session wrapper to <code>/usr/bin/</code> and a <code>.desktop</code> file to <code>/usr/share/xsessions/</code> If run as a regular user, they will install the program to <code>~/bin/9/</code> and not install the manual pages, wrapper, or <code>.desktop</code> file.</p>
|
||||||
|
|
||||||
<p>Building requires <code>plan9port</code> and the <code>libX11</code> and <code>libXT</code> headers. Optionally, <code>libnotify</code> is used to show notifications when switching virtual desktops.</p>
|
<p>Running and building require the following:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>a full <code>plan9port</code> installation</li>
|
||||||
|
<li><code>libX11</code> and development headers</li>
|
||||||
|
<li><code>libXT</code> and development headers</li>
|
||||||
|
<li><code>libXrandr</code> and development headers</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<p>If virtual desktop switching notification is enabled, it requires</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><code>libnotify</code> and development headers</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="CONFIGURATION">CONFIGURATION</h2>
|
<h2 id="CONFIGURATION">CONFIGURATION</h2>
|
||||||
|
|
||||||
|
@ -131,6 +146,8 @@
|
||||||
|
|
||||||
<p>Alt-Tab cycles focus through all windows on the current desktop.</p>
|
<p>Alt-Tab cycles focus through all windows on the current desktop.</p>
|
||||||
|
|
||||||
|
<p>Multimonitor support via <code>Xrandr(3)</code> is supported; keybinds should properly interpret the monitor the current window occupies (for <code>Tile-</code>, <code>Maximize</code>, etc) or the monitor the cursor is on (<code>Launch</code>)</p>
|
||||||
|
|
||||||
<p>The following operations are bindable to key combinations (shown are the default bindings):</p>
|
<p>The following operations are bindable to key combinations (shown are the default bindings):</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -158,13 +175,11 @@
|
||||||
|
|
||||||
<h2 id="BUGS-AND-CAVEATS">BUGS AND CAVEATS</h2>
|
<h2 id="BUGS-AND-CAVEATS">BUGS AND CAVEATS</h2>
|
||||||
|
|
||||||
<p>Multimonitor output is not currently supported -- the whole "screen" (collection of active monitors) is treated as one monitor, and keybinds and automatic window placement will not work properly.</p>
|
|
||||||
|
|
||||||
<p>Click events don't pass through when clicking to activate a window.</p>
|
<p>Click events don't pass through when clicking to activate a window.</p>
|
||||||
|
|
||||||
<p>Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window. I personally sometimes find this behavior useful.</p>
|
<p>Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window. I personally sometimes find this behavior useful.</p>
|
||||||
|
|
||||||
<p>Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so.</p>
|
<p>Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so. If the program expects to run at the current screen resolution, the window-wrangling heuristics should maximize it and you'll be golden. If the window is in override-redirect mode, it should just run fullscreen without a hitch.</p>
|
||||||
|
|
||||||
<p>Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset. Maximize the window after opening and it should be good.</p>
|
<p>Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset. Maximize the window after opening and it should be good.</p>
|
||||||
|
|
||||||
|
@ -173,20 +188,20 @@
|
||||||
<h2 id="AUTHORS">AUTHORS</h2>
|
<h2 id="AUTHORS">AUTHORS</h2>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Derek Stevens <a href="mailto:nilix@nilfm.cc" data-bare-link="true">nilix@nilfm.cc</a></li>
|
<li>Derek Stevens <a href="mailto:nilix@nilfm.cc" data-bare-link="true">nilix@nilfm.cc</a></li>
|
||||||
<li>Russ Cox <a href="mailto:rsc@swtch.com" data-bare-link="true">rsc@swtch.com</a></li>
|
<li>Russ Cox <a href="mailto:rsc@swtch.com" data-bare-link="true">rsc@swtch.com</a></li>
|
||||||
<li>David Hogan, RIP</li>
|
<li>David Hogan, RIP</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="SEE-ALSO">SEE ALSO</h2>
|
<h2 id="SEE-ALSO">SEE ALSO</h2>
|
||||||
|
|
||||||
<p><span class="man-ref">rio<span class="s">(1)</span></span>, <span class="man-ref">9term<span class="s">(1)</span></span></p>
|
<p><span class="man-ref">rio<span class="s">(1)</span></span>, <span class="man-ref">9term<span class="s">(1)</span></span>, <span class="man-ref">xrandr<span class="s">(1)</span></span>, <span class="man-ref">Xrandr<span class="s">(3)</span></span></p>
|
||||||
|
|
||||||
|
|
||||||
<ol class='man-decor man-foot man foot'>
|
<ol class='man-decor man-foot man foot'>
|
||||||
<li class='tl'></li>
|
<li class='tl'></li>
|
||||||
<li class='tc'>November 2021</li>
|
<li class='tc'>February 2022</li>
|
||||||
<li class='tr'>ryudo(1)</li>
|
<li class='tr'>ryudo(1)</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
|
22
ryudo.1.md
22
ryudo.1.md
|
@ -26,7 +26,16 @@ If either `exit` or `restart` is given, the appropriate message is sent to an al
|
||||||
|
|
||||||
Run the provided `build.sh` and `install.sh` scripts to build and install `ryudo`. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the `startryudo` session wrapper to `/usr/bin/` and a `.desktop` file to `/usr/share/xsessions/` If run as a regular user, they will install the program to `~/bin/9/` and not install the manual pages, wrapper, or `.desktop` file.
|
Run the provided `build.sh` and `install.sh` scripts to build and install `ryudo`. If run as root, they will install the program and manual pages to the PLAN9 installation path and install the `startryudo` session wrapper to `/usr/bin/` and a `.desktop` file to `/usr/share/xsessions/` If run as a regular user, they will install the program to `~/bin/9/` and not install the manual pages, wrapper, or `.desktop` file.
|
||||||
|
|
||||||
Building requires `plan9port` and the `libX11` and `libXT` headers. Optionally, `libnotify` is used to show notifications when switching virtual desktops.
|
Running and building require the following:
|
||||||
|
|
||||||
|
* a full `plan9port` installation
|
||||||
|
* `libX11` and development headers
|
||||||
|
* `libXT` and development headers
|
||||||
|
* `libXrandr` and development headers
|
||||||
|
|
||||||
|
If virtual desktop switching notification is enabled, it requires
|
||||||
|
|
||||||
|
* `libnotify` and development headers
|
||||||
|
|
||||||
## CONFIGURATION
|
## CONFIGURATION
|
||||||
|
|
||||||
|
@ -45,7 +54,7 @@ Right-clicking on the desktop or an inactive window opens a menu with the follow
|
||||||
- `Stick`: Not enabled by default. Click mouse button 3 on a window to toggle its stickiness. If sticky, it will be present on all virtual desktops. If made unsticky, the window will be restricted to the current virtual desktop.
|
- `Stick`: Not enabled by default. Click mouse button 3 on a window to toggle its stickiness. If sticky, it will be present on all virtual desktops. If made unsticky, the window will be restricted to the current virtual desktop.
|
||||||
- `Delete`: Closes a window. Click the window to close with mouse button 3. `SIGHUP` (hangup signal) is sent to all processes in the window's process group.
|
- `Delete`: Closes a window. Click the window to close with mouse button 3. `SIGHUP` (hangup signal) is sent to all processes in the window's process group.
|
||||||
- `Hide`: Minimize a window. Click the window with mouse button 3. It will be hidden and its label truncated and appended to the menu. There is a compiled-in limit of 128 hidden windows.
|
- `Hide`: Minimize a window. Click the window with mouse button 3. It will be hidden and its label truncated and appended to the menu. There is a compiled-in limit of 128 hidden windows.
|
||||||
- `LABEL`: Select any label after the `Hide` option to restore it to the current virtual desktop.
|
- `LABEL`: Select any label after the `Hide` option to restore the window it represents to the current virtual desktop.
|
||||||
|
|
||||||
Windows may be arranged by dragging their borders. Mouse buttons 1 or 2 can be used to drag an individual side/corner of a window around, resizing it. Mouse button 3 can be used to move the whole window.
|
Windows may be arranged by dragging their borders. Mouse buttons 1 or 2 can be used to drag an individual side/corner of a window around, resizing it. Mouse button 3 can be used to move the whole window.
|
||||||
|
|
||||||
|
@ -55,6 +64,8 @@ Mouse button 1 focuses a window. The click is not transferred to the window (you
|
||||||
|
|
||||||
Alt-Tab cycles focus through all windows on the current desktop.
|
Alt-Tab cycles focus through all windows on the current desktop.
|
||||||
|
|
||||||
|
Multimonitor support via `Xrandr(3)` is supported; keybinds should properly interpret the monitor the current window occupies (for `Tile-`, `Maximize`, etc) or the monitor the cursor is on (`Launch`)
|
||||||
|
|
||||||
The following operations are bindable to key combinations (shown are the default bindings):
|
The following operations are bindable to key combinations (shown are the default bindings):
|
||||||
|
|
||||||
- `Launch` (Super + /): Open a new terminal in the center of the screen and make it active.
|
- `Launch` (Super + /): Open a new terminal in the center of the screen and make it active.
|
||||||
|
@ -65,6 +76,7 @@ The following operations are bindable to key combinations (shown are the default
|
||||||
- `Unhide` (Super + U): Restore the most recently minimized window.
|
- `Unhide` (Super + U): Restore the most recently minimized window.
|
||||||
- `Delete` (Super + D): Close the currently active window.
|
- `Delete` (Super + D): Close the currently active window.
|
||||||
- `Stick` (Super + S): Toggle stickiness of the currently active window.
|
- `Stick` (Super + S): Toggle stickiness of the currently active window.
|
||||||
|
- `Wrangle` (Super + A): Wrangle the currently active window to another monitor (this follows the order of the monitors given by `Xrandr`'s `XRRGetMonitors` function and may not correspond to the actual visible order of the monitors -- wrangling doesn't change the active window, so you can repeat the operation until the window is on the desired monitor.
|
||||||
- `Zoom` (Super + Z): Toggle zoom mode. In zoom mode, the currently active window is maximized, new windows are opened maximized, and using Alt-Tab to switch to another window maximizes it.
|
- `Zoom` (Super + Z): Toggle zoom mode. In zoom mode, the currently active window is maximized, new windows are opened maximized, and using Alt-Tab to switch to another window maximizes it.
|
||||||
- `Tile Left` (Super + H): Tile the currently active window to fill the left half of the screen.
|
- `Tile Left` (Super + H): Tile the currently active window to fill the left half of the screen.
|
||||||
- `Tile Right` (Super + L): Tile the currently active window to fill the right half of the screen.
|
- `Tile Right` (Super + L): Tile the currently active window to fill the right half of the screen.
|
||||||
|
@ -79,13 +91,11 @@ The following operations are bindable to key combinations (shown are the default
|
||||||
|
|
||||||
## BUGS AND CAVEATS
|
## BUGS AND CAVEATS
|
||||||
|
|
||||||
Multimonitor output is not currently supported -- the whole "screen" (collection of active monitors) is treated as one monitor, and keybinds and automatic window placement will not work properly.
|
|
||||||
|
|
||||||
Click events don't pass through when clicking to activate a window.
|
Click events don't pass through when clicking to activate a window.
|
||||||
|
|
||||||
Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window. I personally sometimes find this behavior useful.
|
Clicking mouse button 2/3 on an inactive window brings up the Button 2/3 Menu instead of focusing the window. I personally sometimes find this behavior useful.
|
||||||
|
|
||||||
Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so.
|
Programs that expect to run fullscreen will probably just open in a window the size of whatever resolution they expect to run at. Depending on the implementation, they may respond well to being maximized or you may have to change your screen resolution manually before doing so. If the program expects to run at the current screen resolution, the window-wrangling heuristics should maximize it and you'll be golden. If the window is in override-redirect mode, it should just run fullscreen without a hitch.
|
||||||
|
|
||||||
Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset. Maximize the window after opening and it should be good.
|
Fullscreen Virtualbox VM windows are a strange outlier and start with their graphics offset. Maximize the window after opening and it should be good.
|
||||||
|
|
||||||
|
@ -99,4 +109,4 @@ While there is naitive support for per-window opacity via the `OPACITY` and `TRA
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
|
|
||||||
rio(1), 9term(1)
|
rio(1), 9term(1), xrandr(1), Xrandr(3)
|
||||||
|
|
Loading…
Reference in a new issue