aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--a.out0
-rw-r--r--go.mod5
-rw-r--r--go.sum2
-rw-r--r--keysym/keysim.go234
-rw-r--r--main.go255
-rwxr-xr-xwmbin0 -> 4218392 bytes
-rwxr-xr-xxneststart2
7 files changed, 498 insertions, 0 deletions
diff --git a/a.out b/a.out
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/a.out
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..4216f68
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,5 @@
+module github.com/crecheer/wm
+
+go 1.25.0
+
+require github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc // indirect
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..ae50bbf
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,2 @@
+github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc h1:7D+Bh06CRPCJO3gr2F7h1sriovOZ8BMhca2Rg85c2nk=
+github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
diff --git a/keysym/keysim.go b/keysym/keysim.go
new file mode 100644
index 0000000..831ee4e
--- /dev/null
+++ b/keysym/keysim.go
@@ -0,0 +1,234 @@
+package keysym
+
+// copied from https://github.com/driusan/dewm/blob/master/keysym/keysym.go
+
+// Known KeySyms from /usr/include/X11/keysymdef.h
+const (
+ // TTY function keys, cleverly chosen to map to ASCII, for convenience of
+ // programming, but could have been arbitrary (at the cost of lookup
+ // tables in client code).
+ XK_BackSpace = 0xff08 // Back space, back char
+ XK_Tab = 0xff09
+ XK_Linefeed = 0xff0a // Linefeed, LF
+ XK_Clear = 0xff0b
+ XK_Return = 0xff0d // Return, enter
+ XK_Pause = 0xff13 // Pause, hold
+ XK_Scroll_Lock = 0xff14
+ XK_Sys_Req = 0xff15
+ XK_Escape = 0xff1b
+ XK_Delete = 0xffff // Delete, rubout
+ // Latin 1
+ // (ISO/IEC 8859-1 = Unicode U+0020..U+00FF)
+ // Byte 3 = 0
+ XK_space = 0x0020 // U+0020 SPACE
+ XK_exclam = 0x0021 // U+0021 EXCLAMATION MARK
+ XK_quotedbl = 0x0022 // U+0022 QUOTATION MARK
+ XK_numbersign = 0x0023 // U+0023 NUMBER SIGN
+ XK_dollar = 0x0024 // U+0024 DOLLAR SIGN
+ XK_percent = 0x0025 // U+0025 PERCENT SIGN
+ XK_ampersand = 0x0026 // U+0026 AMPERSAND
+ XK_apostrophe = 0x0027 // U+0027 APOSTROPHE
+ XK_quoteright = 0x0027 // deprecated
+ XK_parenleft = 0x0028 // U+0028 LEFT PARENTHESIS
+ XK_parenright = 0x0029 // U+0029 RIGHT PARENTHESIS
+ XK_asterisk = 0x002a // U+002A ASTERISK
+ XK_plus = 0x002b // U+002B PLUS SIGN
+ XK_comma = 0x002c // U+002C COMMA
+ XK_minus = 0x002d // U+002D HYPHEN-MINUS
+ XK_period = 0x002e // U+002E FULL STOP
+ XK_slash = 0x002f // U+002F SOLIDUS
+ XK_0 = 0x0030 // U+0030 DIGIT ZERO
+ XK_1 = 0x0031 // U+0031 DIGIT ONE
+ XK_2 = 0x0032 // U+0032 DIGIT TWO
+ XK_3 = 0x0033 // U+0033 DIGIT THREE
+ XK_4 = 0x0034 // U+0034 DIGIT FOUR
+ XK_5 = 0x0035 // U+0035 DIGIT FIVE
+ XK_6 = 0x0036 // U+0036 DIGIT SIX
+ XK_7 = 0x0037 // U+0037 DIGIT SEVEN
+ XK_8 = 0x0038 // U+0038 DIGIT EIGHT
+ XK_9 = 0x0039 // U+0039 DIGIT NINE
+ XK_colon = 0x003a // U+003A COLON
+ XK_semicolon = 0x003b // U+003B SEMICOLON
+ XK_less = 0x003c // U+003C LESS-THAN SIGN
+ XK_equal = 0x003d // U+003D EQUALS SIGN
+ XK_greater = 0x003e // U+003E GREATER-THAN SIGN
+ XK_question = 0x003f // U+003F QUESTION MARK
+ XK_at = 0x0040 // U+0040 COMMERCIAL AT
+ XK_A = 0x0041 // U+0041 LATIN CAPITAL LETTER A
+ XK_B = 0x0042 // U+0042 LATIN CAPITAL LETTER B
+ XK_C = 0x0043 // U+0043 LATIN CAPITAL LETTER C
+ XK_D = 0x0044 // U+0044 LATIN CAPITAL LETTER D
+ XK_E = 0x0045 // U+0045 LATIN CAPITAL LETTER E
+ XK_F = 0x0046 // U+0046 LATIN CAPITAL LETTER F
+ XK_G = 0x0047 // U+0047 LATIN CAPITAL LETTER G
+ XK_H = 0x0048 // U+0048 LATIN CAPITAL LETTER H
+ XK_I = 0x0049 // U+0049 LATIN CAPITAL LETTER I
+ XK_J = 0x004a // U+004A LATIN CAPITAL LETTER J
+ XK_K = 0x004b // U+004B LATIN CAPITAL LETTER K
+ XK_L = 0x004c // U+004C LATIN CAPITAL LETTER L
+ XK_M = 0x004d // U+004D LATIN CAPITAL LETTER M
+ XK_N = 0x004e // U+004E LATIN CAPITAL LETTER N
+ XK_O = 0x004f // U+004F LATIN CAPITAL LETTER O
+ XK_P = 0x0050 // U+0050 LATIN CAPITAL LETTER P
+ XK_Q = 0x0051 // U+0051 LATIN CAPITAL LETTER Q
+ XK_R = 0x0052 // U+0052 LATIN CAPITAL LETTER R
+ XK_S = 0x0053 // U+0053 LATIN CAPITAL LETTER S
+ XK_T = 0x0054 // U+0054 LATIN CAPITAL LETTER T
+ XK_U = 0x0055 // U+0055 LATIN CAPITAL LETTER U
+ XK_V = 0x0056 // U+0056 LATIN CAPITAL LETTER V
+ XK_W = 0x0057 // U+0057 LATIN CAPITAL LETTER W
+ XK_X = 0x0058 // U+0058 LATIN CAPITAL LETTER X
+ XK_Y = 0x0059 // U+0059 LATIN CAPITAL LETTER Y
+ XK_Z = 0x005a // U+005A LATIN CAPITAL LETTER Z
+ XK_bracketleft = 0x005b // U+005B LEFT SQUARE BRACKET
+ XK_backslash = 0x005c // U+005C REVERSE SOLIDUS
+ XK_bracketright = 0x005d // U+005D RIGHT SQUARE BRACKET
+ XK_asciicircum = 0x005e // U+005E CIRCUMFLEX ACCENT
+ XK_underscore = 0x005f // U+005F LOW LINE
+ XK_grave = 0x0060 // U+0060 GRAVE ACCENT
+ XK_quoteleft = 0x0060 // deprecated
+ XK_a = 0x0061 // U+0061 LATIN SMALL LETTER A
+ XK_b = 0x0062 // U+0062 LATIN SMALL LETTER B
+ XK_c = 0x0063 // U+0063 LATIN SMALL LETTER C
+ XK_d = 0x0064 // U+0064 LATIN SMALL LETTER D
+ XK_e = 0x0065 // U+0065 LATIN SMALL LETTER E
+ XK_f = 0x0066 // U+0066 LATIN SMALL LETTER F
+ XK_g = 0x0067 // U+0067 LATIN SMALL LETTER G
+ XK_h = 0x0068 // U+0068 LATIN SMALL LETTER H
+ XK_i = 0x0069 // U+0069 LATIN SMALL LETTER I
+ XK_j = 0x006a // U+006A LATIN SMALL LETTER J
+ XK_k = 0x006b // U+006B LATIN SMALL LETTER K
+ XK_l = 0x006c // U+006C LATIN SMALL LETTER L
+ XK_m = 0x006d // U+006D LATIN SMALL LETTER M
+ XK_n = 0x006e // U+006E LATIN SMALL LETTER N
+ XK_o = 0x006f // U+006F LATIN SMALL LETTER O
+ XK_p = 0x0070 // U+0070 LATIN SMALL LETTER P
+ XK_q = 0x0071 // U+0071 LATIN SMALL LETTER Q
+ XK_r = 0x0072 // U+0072 LATIN SMALL LETTER R
+ XK_s = 0x0073 // U+0073 LATIN SMALL LETTER S
+ XK_t = 0x0074 // U+0074 LATIN SMALL LETTER T
+ XK_u = 0x0075 // U+0075 LATIN SMALL LETTER U
+ XK_v = 0x0076 // U+0076 LATIN SMALL LETTER V
+ XK_w = 0x0077 // U+0077 LATIN SMALL LETTER W
+ XK_x = 0x0078 // U+0078 LATIN SMALL LETTER X
+ XK_y = 0x0079 // U+0079 LATIN SMALL LETTER Y
+ XK_z = 0x007a // U+007A LATIN SMALL LETTER Z
+ XK_braceleft = 0x007b // U+007B LEFT CURLY BRACKET
+ XK_bar = 0x007c // U+007C VERTICAL LINE
+ XK_braceright = 0x007d // U+007D RIGHT CURLY BRACKET
+ XK_asciitilde = 0x007e // U+007E TILDE
+
+ XK_nobreakspace = 0x00a0 // U+00A0 NO-BREAK SPACE
+ XK_exclamdown = 0x00a1 // U+00A1 INVERTED EXCLAMATION MARK
+ XK_cent = 0x00a2 // U+00A2 CENT SIGN
+ XK_sterling = 0x00a3 // U+00A3 POUND SIGN
+ XK_currency = 0x00a4 // U+00A4 CURRENCY SIGN
+ XK_yen = 0x00a5 // U+00A5 YEN SIGN
+ XK_brokenbar = 0x00a6 // U+00A6 BROKEN BAR
+ XK_section = 0x00a7 // U+00A7 SECTION SIGN
+ XK_diaeresis = 0x00a8 // U+00A8 DIAERESIS
+ XK_copyright = 0x00a9 // U+00A9 COPYRIGHT SIGN
+ XK_ordfeminine = 0x00aa // U+00AA FEMININE ORDINAL INDICATOR
+ XK_guillemotleft = 0x00ab // U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+ XK_notsign = 0x00ac // U+00AC NOT SIGN
+ XK_hyphen = 0x00ad // U+00AD SOFT HYPHEN
+ XK_registered = 0x00ae // U+00AE REGISTERED SIGN
+ XK_macron = 0x00af // U+00AF MACRON
+ XK_degree = 0x00b0 // U+00B0 DEGREE SIGN
+ XK_plusminus = 0x00b1 // U+00B1 PLUS-MINUS SIGN
+ XK_twosuperior = 0x00b2 // U+00B2 SUPERSCRIPT TWO
+ XK_threesuperior = 0x00b3 // U+00B3 SUPERSCRIPT THREE
+ XK_acute = 0x00b4 // U+00B4 ACUTE ACCENT
+ XK_mu = 0x00b5 // U+00B5 MICRO SIGN
+ XK_paragraph = 0x00b6 // U+00B6 PILCROW SIGN
+ XK_periodcentered = 0x00b7 // U+00B7 MIDDLE DOT
+ XK_cedilla = 0x00b8 // U+00B8 CEDILLA
+ XK_onesuperior = 0x00b9 // U+00B9 SUPERSCRIPT ONE
+ XK_masculine = 0x00ba // U+00BA MASCULINE ORDINAL INDICATOR
+ XK_guillemotright = 0x00bb // U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+ XK_onequarter = 0x00bc // U+00BC VULGAR FRACTION ONE QUARTER
+ XK_onehalf = 0x00bd // U+00BD VULGAR FRACTION ONE HALF
+ XK_threequarters = 0x00be // U+00BE VULGAR FRACTION THREE QUARTERS
+ XK_questiondown = 0x00bf // U+00BF INVERTED QUESTION MARK
+ XK_Agrave = 0x00c0 // U+00C0 LATIN CAPITAL LETTER A WITH GRAVE
+ XK_Aacute = 0x00c1 // U+00C1 LATIN CAPITAL LETTER A WITH ACUTE
+ XK_Acircumflex = 0x00c2 // U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX
+ XK_Atilde = 0x00c3 // U+00C3 LATIN CAPITAL LETTER A WITH TILDE
+ XK_Adiaeresis = 0x00c4 // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS
+ XK_Aring = 0x00c5 // U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
+ XK_AE = 0x00c6 // U+00C6 LATIN CAPITAL LETTER AE
+ XK_Ccedilla = 0x00c7 // U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA
+ XK_Egrave = 0x00c8 // U+00C8 LATIN CAPITAL LETTER E WITH GRAVE
+ XK_Eacute = 0x00c9 // U+00C9 LATIN CAPITAL LETTER E WITH ACUTE
+ XK_Ecircumflex = 0x00ca // U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX
+ XK_Ediaeresis = 0x00cb // U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS
+ XK_Igrave = 0x00cc // U+00CC LATIN CAPITAL LETTER I WITH GRAVE
+ XK_Iacute = 0x00cd // U+00CD LATIN CAPITAL LETTER I WITH ACUTE
+ XK_Icircumflex = 0x00ce // U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX
+ XK_Idiaeresis = 0x00cf // U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS
+ XK_ETH = 0x00d0 // U+00D0 LATIN CAPITAL LETTER ETH
+ XK_Eth = 0x00d0 // deprecated
+ XK_Ntilde = 0x00d1 // U+00D1 LATIN CAPITAL LETTER N WITH TILDE
+ XK_Ograve = 0x00d2 // U+00D2 LATIN CAPITAL LETTER O WITH GRAVE
+ XK_Oacute = 0x00d3 // U+00D3 LATIN CAPITAL LETTER O WITH ACUTE
+ XK_Ocircumflex = 0x00d4 // U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX
+ XK_Otilde = 0x00d5 // U+00D5 LATIN CAPITAL LETTER O WITH TILDE
+ XK_Odiaeresis = 0x00d6 // U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS
+ XK_multiply = 0x00d7 // U+00D7 MULTIPLICATION SIGN
+ XK_Oslash = 0x00d8 // U+00D8 LATIN CAPITAL LETTER O WITH STROKE
+ XK_Ooblique = 0x00d8 // U+00D8 LATIN CAPITAL LETTER O WITH STROKE
+ XK_Ugrave = 0x00d9 // U+00D9 LATIN CAPITAL LETTER U WITH GRAVE
+ XK_Uacute = 0x00da // U+00DA LATIN CAPITAL LETTER U WITH ACUTE
+ XK_Ucircumflex = 0x00db // U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX
+ XK_Udiaeresis = 0x00dc // U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS
+ XK_Yacute = 0x00dd // U+00DD LATIN CAPITAL LETTER Y WITH ACUTE
+ XK_THORN = 0x00de // U+00DE LATIN CAPITAL LETTER THORN
+ XK_Thorn = 0x00de // deprecated
+ XK_ssharp = 0x00df // U+00DF LATIN SMALL LETTER SHARP S
+ XK_agrave = 0x00e0 // U+00E0 LATIN SMALL LETTER A WITH GRAVE
+ XK_aacute = 0x00e1 // U+00E1 LATIN SMALL LETTER A WITH ACUTE
+ XK_acircumflex = 0x00e2 // U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX
+ XK_atilde = 0x00e3 // U+00E3 LATIN SMALL LETTER A WITH TILDE
+ XK_adiaeresis = 0x00e4 // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS
+ XK_aring = 0x00e5 // U+00E5 LATIN SMALL LETTER A WITH RING ABOVE
+ XK_ae = 0x00e6 // U+00E6 LATIN SMALL LETTER AE
+ XK_ccedilla = 0x00e7 // U+00E7 LATIN SMALL LETTER C WITH CEDILLA
+ XK_egrave = 0x00e8 // U+00E8 LATIN SMALL LETTER E WITH GRAVE
+ XK_eacute = 0x00e9 // U+00E9 LATIN SMALL LETTER E WITH ACUTE
+ XK_ecircumflex = 0x00ea // U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX
+ XK_ediaeresis = 0x00eb // U+00EB LATIN SMALL LETTER E WITH DIAERESIS
+ XK_igrave = 0x00ec // U+00EC LATIN SMALL LETTER I WITH GRAVE
+ XK_iacute = 0x00ed // U+00ED LATIN SMALL LETTER I WITH ACUTE
+ XK_icircumflex = 0x00ee // U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX
+ XK_idiaeresis = 0x00ef // U+00EF LATIN SMALL LETTER I WITH DIAERESIS
+ XK_eth = 0x00f0 // U+00F0 LATIN SMALL LETTER ETH
+ XK_ntilde = 0x00f1 // U+00F1 LATIN SMALL LETTER N WITH TILDE
+ XK_ograve = 0x00f2 // U+00F2 LATIN SMALL LETTER O WITH GRAVE
+ XK_oacute = 0x00f3 // U+00F3 LATIN SMALL LETTER O WITH ACUTE
+ XK_ocircumflex = 0x00f4 // U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX
+ XK_otilde = 0x00f5 // U+00F5 LATIN SMALL LETTER O WITH TILDE
+ XK_odiaeresis = 0x00f6 // U+00F6 LATIN SMALL LETTER O WITH DIAERESIS
+ XK_division = 0x00f7 // U+00F7 DIVISION SIGN
+ XK_oslash = 0x00f8 // U+00F8 LATIN SMALL LETTER O WITH STROKE
+ XK_ooblique = 0x00f8 // U+00F8 LATIN SMALL LETTER O WITH STROKE
+ XK_ugrave = 0x00f9 // U+00F9 LATIN SMALL LETTER U WITH GRAVE
+ XK_uacute = 0x00fa // U+00FA LATIN SMALL LETTER U WITH ACUTE
+ XK_ucircumflex = 0x00fb // U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX
+ XK_udiaeresis = 0x00fc // U+00FC LATIN SMALL LETTER U WITH DIAERESIS
+ XK_yacute = 0x00fd // U+00FD LATIN SMALL LETTER Y WITH ACUTE
+ XK_thorn = 0x00fe // U+00FE LATIN SMALL LETTER THORN
+ XK_ydiaeresis = 0x00ff // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS
+
+ // Cursor control & motion
+ XK_Home = 0xff50
+ XK_Left = 0xff51 // Move left, left arrow
+ XK_Up = 0xff52 // Move up, up arrow
+ XK_Right = 0xff53 // Move right, right arrow
+ XK_Down = 0xff54 // Move down, down arrow
+ XK_Prior = 0xff55 // Prior, previous
+ XK_Page_Up = 0xff55
+ XK_Next = 0xff56 // Next
+ XK_Page_Down = 0xff56
+ XK_End = 0xff57 // EOL
+ XK_Begin = 0xff58 // BOL
+) \ No newline at end of file
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..b6cb1f4
--- /dev/null
+++ b/main.go
@@ -0,0 +1,255 @@
+package main
+
+import (
+ "log"
+ "os"
+ "os/exec"
+
+ "github.com/BurntSushi/xgb"
+ "github.com/BurntSushi/xgb/xproto"
+
+ "github.com/crecheer/wm/keysym"
+)
+
+// structs
+
+type Key struct {
+ Mod uint16
+ Sym uint32
+ Fn func(*xgb.Conn)
+}
+
+type Client struct {
+ Win xproto.Window
+ X int16
+ Y int16
+ Width uint16
+ Height uint16
+ Floating bool
+}
+
+var keys []Key
+var clients = make(map[xproto.Window]*Client)
+
+func main() {
+ conn, err := xgb.NewConn()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ setup(conn)
+
+ for {
+ log.Println("test")
+ ev, err := conn.WaitForEvent()
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ switch e := ev.(type) {
+ case xproto.KeyPressEvent:
+ handleKeyPress(conn, e)
+
+ case xproto.MapRequestEvent:
+ manageWindow(conn, e.Window)
+
+ case xproto.DestroyNotifyEvent:
+ unmanageWindow(conn, e.Window)
+
+ case xproto.UnmapNotifyEvent:
+ unmanageWindow(conn, e.Window)
+
+ default:
+ log.Println("event: ", e)
+ }
+
+ }
+}
+
+func setup(conn *xgb.Conn) {
+ root := xproto.Setup(conn).DefaultScreen(conn).Root
+
+ err := xproto.ChangeWindowAttributesChecked(
+ conn,
+ root,
+ xproto.CwEventMask,
+ []uint32{
+ xproto.EventMaskSubstructureRedirect |
+ xproto.EventMaskSubstructureNotify,
+ },
+ ).Check()
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ setupKeys(conn)
+}
+
+func spawn(cmd string, args ...string) {
+ c := exec.Command(cmd, args...)
+ c.Stdout = nil
+ c.Stderr = nil
+ c.Stdin = nil
+ if err := c.Start(); err != nil {
+ log.Println("failed to spawn", cmd, ":", err)
+ }
+}
+
+func setupKeys(conn *xgb.Conn) {
+ mod := uint16(xproto.ModMask1) // Alt
+
+ keys = []Key{
+ {
+ Mod: mod,
+ Sym: keysym.XK_Return,
+ Fn: func(c *xgb.Conn) {
+ spawn("st")
+ },
+ },
+ {
+ Mod: mod,
+ Sym: keysym.XK_Q,
+ Fn: func(c *xgb.Conn) {
+ os.Exit(0)
+ },
+ },
+ }
+
+ grabKeys(conn)
+}
+
+func grabKeys(conn *xgb.Conn) {
+ root := xproto.Setup(conn).DefaultScreen(conn).Root
+
+ for _, k := range keys {
+ keycode := keysymToKeycode(conn, k.Sym)
+ if keycode == 0 {
+ continue
+ }
+
+ xproto.GrabKey(conn,
+ true,
+ root,
+ k.Mod,
+ keycode,
+ xproto.GrabModeAsync,
+ xproto.GrabModeAsync,
+ )
+ }
+}
+
+func keysymToKeycode(conn *xgb.Conn, sym uint32) xproto.Keycode {
+ setup := xproto.Setup(conn)
+ min := setup.MinKeycode
+ max := setup.MaxKeycode
+
+ reply, err := xproto.GetKeyboardMapping(conn, min, byte(max-min+1)).Reply()
+ if err != nil {
+ return 0
+ }
+
+ keysymsPerKeycode := int(reply.KeysymsPerKeycode)
+
+ for kc := min; kc <= max; kc++ {
+ for i := 0; i < keysymsPerKeycode; i++ {
+ idx := int(kc-min)*keysymsPerKeycode + i
+ if uint32(reply.Keysyms[idx]) == sym {
+ return kc
+ }
+ }
+ }
+
+ return 0
+}
+
+func handleKeyPress(conn *xgb.Conn, e xproto.KeyPressEvent) {
+ log.Println("key pressed")
+ reply, err := xproto.GetKeyboardMapping(conn, e.Detail, 1).Reply()
+ if err != nil || len(reply.Keysyms) == 0 {
+ return
+ }
+
+
+
+ sym := reply.Keysyms[0]
+
+ for _, k := range keys {
+ if uint32(sym) == k.Sym && (e.State&k.Mod) == k.Mod {
+ k.Fn(conn)
+ }
+ }
+}
+
+func manageWindow(conn *xgb.Conn, win xproto.Window) {
+ geom, err := xproto.GetGeometry(conn, xproto.Drawable(win)).Reply()
+ if err != nil {
+ return
+ }
+
+ client := &Client{
+ Win: win,
+ X: geom.X,
+ Y: geom.Y,
+ Width: geom.Width,
+ Height: geom.Height,
+ Floating: false,
+ }
+
+ clients[win] = client
+ log.Println("managing window:", win)
+
+ // listen for events on this window
+ xproto.ChangeWindowAttributes(conn, win,
+ xproto.CwEventMask,
+ []uint32{
+ xproto.EventMaskEnterWindow |
+ xproto.EventMaskFocusChange |
+ xproto.EventMaskPropertyChange,
+ })
+
+ // map (show) window
+ xproto.MapWindow(conn, win)
+
+ // tile all windows
+ tile(conn)
+}
+
+func unmanageWindow(conn *xgb.Conn, win xproto.Window) {
+ if _, ok := clients[win]; ok {
+ log.Println("unmanaging window:", win)
+ delete(clients, win)
+ tile(conn)
+ }
+}
+
+func tile(conn *xgb.Conn) {
+ log.Println("tile")
+ screen := xproto.Setup(conn).DefaultScreen(conn)
+ screenWidth := int(screen.WidthInPixels)
+ screenHeight := int(screen.HeightInPixels)
+
+ n := len(clients)
+ if n == 0 {
+ return
+ }
+
+ i := 0
+ for _, c := range clients {
+ height := screenHeight / n
+
+ xproto.ConfigureWindow(conn, c.Win,
+ xproto.ConfigWindowX|
+ xproto.ConfigWindowY|
+ xproto.ConfigWindowWidth|
+ xproto.ConfigWindowHeight,
+ []uint32{
+ 0,
+ uint32(i * height),
+ uint32(screenWidth),
+ uint32(height),
+ })
+
+ i++
+ }
+}
diff --git a/wm b/wm
new file mode 100755
index 0000000..9364c4c
--- /dev/null
+++ b/wm
Binary files differ
diff --git a/xneststart b/xneststart
new file mode 100755
index 0000000..6d91d3d
--- /dev/null
+++ b/xneststart
@@ -0,0 +1,2 @@
+Xnest :2 -geometry 1280x800 &
+DISPLAY=:2 ./wm \ No newline at end of file