Browse Source

Got it working

master
Wesley Kerfoot 4 years ago
parent
commit
e6d9825299
  1. 171
      src/nimwin.nim

171
src/nimwin.nim

@ -1,32 +1,93 @@
import x11/xlib, x11/xutil, x11/x, x11/keysym import x11/xlib, x11/xutil, x11/x, x11/keysym
import strformat, os, options, tables, random
type XDirection = enum left, right
type YDirection = enum up, down
type Window = ref object of RootObj
x : cint
y : cint
width : cint
height : cint
speed : cint
win : TWindow
xDirection : XDirection
yDirection : YDirection
var root : TWindow
var windowState : Table[TWindow, Window] = initTable[TWindow, Window]()
var invalidWindows : seq[TWindow]
proc getWindowName(display : PDisplay, window : TWindow) : Option[string] =
var name : cstring
if display.XFetchName(window, name.addr) == BadWindow:
return none(string)
some($name)
proc setWindowName(display : PDisplay, window : TWindow, name : cstring) : Option[string] =
if display.XStoreName(window, name) == BadWindow:
return none(string)
some($name)
proc gcWindows(display : PDisplay) =
for xid, window in windowState.pairs:
discard display.getWindowName(xid)
for xid in invalidWindows:
windowState.del(xid)
invalidWindows = @[]
proc ignoreBadWindows(display : PDisplay, ev : PXErrorEvent) : cint {.cdecl.} =
# resourceID maps to the Window's XID
invalidWindows &= @[ev.resourceID]
0
proc getDisplay : PDisplay = proc getDisplay : PDisplay =
result = XOpenDisplay(nil) result = XOpenDisplay(nil)
if result == nil: if result == nil:
quit("Failed to open display") quit("Failed to open display")
proc grabMouse(display : PDisplay, button : int) = iterator getChildren(display : PDisplay, rootHeight : int, rootWidth : int) : Window =
discard XGrabButton(display, var currentWindow : PWindow
button.cuint, var rootReturn : TWindow
Mod1Mask.cuint, var parentReturn : TWindow
DefaultRootWindow(display), var childrenReturn : PWindow
1.cint, var nChildrenReturn : cuint
ButtonPressMask or ButtonReleaseMask or PointerMotionMask,
GrabModeAsync, # Seed the RNG
GrabModeAsync, randomize()
None,
None) discard XQueryTree(display,
root,
proc grabKeys(display : PDisplay) = rootReturn.addr,
let keyModifier = "F1" parentReturn.addr,
discard XGrabKey(display, childrenReturn.addr,
XKeySymToKeyCode(display, nChildrenReturn.addr)
XStringToKeySym(keyModifier.cstring)).cint,
Mod1Mask.cuint,
DefaultRootWindow(display), for i in 0..(nChildrenReturn.int - 1):
1.cint, var attr : TXWindowAttributes
GrabModeAsync.cint,
GrabModeAsync.cint) currentWindow = cast[PWindow](
cast[uint](childrenReturn) + cast[uint](i * currentWindow[].sizeof)
)
if display.XGetWindowAttributes(currentWindow[], attr.addr) == BadWindow:
windowState.del(currentWindow[])
continue
yield Window(
x: rand(0..rootWidth).cint,
y: rand(0..rootHeight).cint,
xDirection: right,
yDirection: down,
width: attr.width,
height: attr.height,
win: currentWindow[],
speed: 10
)
discard XFree(childrenReturn)
when isMainModule: when isMainModule:
var start : TXButtonEvent var start : TXButtonEvent
@ -35,39 +96,51 @@ when isMainModule:
let display = getDisplay() let display = getDisplay()
display.grabKeys root = DefaultRootWindow(display)
display.grabMouse(1)
display.grabMouse(3)
start.subWindow = None start.subWindow = None
while true: discard XSetErrorHandler(ignoreBadWindows)
# TODO refactor using XPending ? discard display.XGetWindowAttributes(root, attr.addr)
discard XNextEvent(display, ev.addr)
# subwindow is because we grabbed the root window let rootWidth = attr.width
# and we want events in its children let rootHeight = attr.height
if (ev.theType == KeyPress) and (ev.xKey.subWindow != None): while true:
discard XRaiseWindow(display, ev.xKey.subWindow) sleep(10)
elif (ev.theType == ButtonPress) and (ev.xButton.subWindow != None): for window in getChildren(display, rootHeight, rootWidth):
discard XGetWindowAttributes(display, ev.xButton.subWindow, attr.addr) # go through each window, add it to the state
start = ev.xButton discard windowState.hasKeyOrPut(window.win, window)
elif (ev.theType == MotionNotify) and (start.subWindow != None): display.gcWindows()
var xDiff : int = ev.xButton.xRoot - start.xRoot
var yDiff : int = ev.xButton.yRoot - start.yRoot
discard XMoveResizeWindow(display, # Go through each window and move them, update the state, etc
start.subWindow, for window in windowState.values:
attr.x + (if start.button == 1: xDiff else: 0).cint, if window.xDirection == right:
attr.y + (if start.button == 1: yDiff else: 0).cint, if window.x == (rootWidth - window.width) or window.x > rootWidth:
max(1, attr.width + (if start.button == 3: xDiff else: 0)).cuint, windowState[window.win].xDirection = left
max(1, attr.height + (if start.button == 3: yDiff else: 0)).cuint) windowState[window.win].x -= 1
else:
windowState[window.win].x += 1
else:
if window.x <= 0:
windowState[window.win].xDirection = right
windowState[window.win].x += 1
else:
windowState[window.win].x -= 1
elif ev.theType == ButtonRelease: if window.yDirection == up:
start.subWindow = None if window.y <= 0:
windowState[window.win].yDirection = down
windowState[window.win].y += 1
else:
windowState[window.win].y -= 1
else:
if window.y >= (rootHeight - window.height):
windowState[window.win].yDirection = up
windowState[window.win].y -= 1
else:
windowState[window.win].y += 1
else: discard display.XMoveWindow(window.win, windowState[window.win].x, windowState[window.win].y)
continue discard display.XSync(0)

Loading…
Cancel
Save