commit 7fe5e95158383e5d8493cb9c8c24b4361c453304 Author: Wesley Kerfoot Date: Sat Mar 28 23:06:25 2020 -0400 initial commit diff --git a/nimwin b/nimwin new file mode 100755 index 0000000..d13dae2 Binary files /dev/null and b/nimwin differ diff --git a/nimwin.nimble b/nimwin.nimble new file mode 100644 index 0000000..f2ebb36 --- /dev/null +++ b/nimwin.nimble @@ -0,0 +1,15 @@ +# Package + +version = "0.1.0" +author = "Wesley Kerfoot" +description = "A Nimble Window Manager" +license = "MIT" +srcDir = "src" +bin = @["nimwin"] + + + +# Dependencies + +requires "nim >= 1" +requires "x11" diff --git a/screenshots/example.gif b/screenshots/example.gif new file mode 100644 index 0000000..cf9238b Binary files /dev/null and b/screenshots/example.gif differ diff --git a/screenshots/example.png b/screenshots/example.png new file mode 100644 index 0000000..f832abc Binary files /dev/null and b/screenshots/example.png differ diff --git a/src/nimwin.nim b/src/nimwin.nim new file mode 100644 index 0000000..60ee8ed --- /dev/null +++ b/src/nimwin.nim @@ -0,0 +1,78 @@ +import x11/xlib, x11/xutil, x11/x, x11/keysym + +proc getDisplay : PDisplay = + result = XOpenDisplay(nil) + if result == nil: + quit("Failed to open display") + +proc grabMouse(display : PDisplay, button : int) = + discard XGrabButton(display, + button.cuint, + Mod1Mask.cuint, + DefaultRootWindow(display), + 1.cint, + ButtonPressMask or ButtonReleaseMask or PointerMotionMask, + GrabModeAsync, + GrabModeAsync, + None, + None) + +proc grabKeys(display : PDisplay) = + let keyModifier = "F1" + discard XGrabKey(display, + XKeySymToKeyCode(display, + XStringToKeySym(keyModifier.cstring)).cint, + Mod1Mask.cuint or Mod2Mask.cuint, + DefaultRootWindow(display), + 1.cint, + GrabModeAsync.cint, + GrabModeAsync.cint) + +when isMainModule: + var start : TXButtonEvent + var ev : TXEvent + var attr : TXWindowAttributes + + let display = getDisplay() + + display.grabKeys + display.grabMouse(1) + display.grabMouse(3) + + start.subWindow = None + + while true: + # TODO refactor using XPending or XCB? + discard XNextEvent(display, ev.addr) + + # subwindow is because we grabbed the root window + # and we want events in its children + + if (ev.theType == KeyPress) and (ev.xKey.subWindow != None): + discard XRaiseWindow(display, ev.xKey.subWindow) + + elif (ev.theType == ButtonPress) and (ev.xButton.subWindow != None): + discard XGetWindowAttributes(display, ev.xButton.subWindow, attr.addr) + start = ev.xButton + + elif (ev.theType == MotionNotify) and (start.subWindow != None): + + # Discard any following MotionNotify events + # This avoids "movement lag" + while display.XCheckTypedEvent(MotionNotify, ev.addr) != 0: continue + + var xDiff : int = ev.xButton.xRoot - start.xRoot + var yDiff : int = ev.xButton.yRoot - start.yRoot + + discard XMoveResizeWindow(display, + start.subWindow, + attr.x + (if start.button == 1: xDiff else: 0).cint, + attr.y + (if start.button == 1: yDiff else: 0).cint, + max(1, attr.width + (if start.button == 3: xDiff else: 0)).cuint, + max(1, attr.height + (if start.button == 3: yDiff else: 0)).cuint) + + elif ev.theType == ButtonRelease: + start.subWindow = None + + else: + continue