Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # cover_x11.nim
- {.passL: "-lX11".}
- type
- Display = distinct pointer
- Window = culong
- Atom = culong
- XSetWindowAttributes = object
- background_pixmap: culong
- background_pixel: culong
- border_pixmap: culong
- border_pixel: culong
- bit_gravity: cint
- win_gravity: cint
- backing_store: cint
- backing_planes: culong
- backing_pixel: culong
- save_under: cint
- event_mask: clong
- do_not_propagate_mask: clong
- override_redirect: cint
- colormap: culong
- cursor: culong
- XClientMessageEvent = object
- theType: cint
- serial: culong
- send_event: cint
- display: Display
- window: Window
- message_type: Atom
- format: cint
- data: array[5, clong]
- XButtonEvent = object
- theType: cint
- serial: culong
- send_event: cint
- display: Display
- window: Window
- root: Window
- subwindow: Window
- time: culong
- x, y: cint
- x_root, y_root: cint
- state: cuint
- button: cuint
- same_screen: cint
- XEvent = array[24, clong]
- MwmHints = object
- flags: culong
- functions: culong
- decorations: culong
- inputMode: clong
- status: culong
- const
- InputOutput = 1
- CWBackPixel = 0x0002
- ExposureMask = 1 shl 15
- ButtonPressMask = 1 shl 2
- StructureNotifyMask = 1 shl 17
- Expose = 12
- ButtonPress = 4
- ClientMessage = 33
- ConfigureNotify = 22
- SubstructureRedirectMask = 1 shl 20
- SubstructureNotifyMask = 1 shl 19
- NET_WM_STATE_ADD = 1
- PropModeReplace = 0
- MWM_HINTS_DECORATIONS = 1 shl 1
- Button1 = 1'u32
- DoubleClickThresholdMs: culong = 400
- WindowSize: cuint = 200
- InitialX: cint = 100
- InitialY: cint = 100
- TopPartHeight: cuint = 25 # set this to match your WM's title bar height
- RightPartWidth: cuint = 2 # extra width to reclaim on the right in borderless mode
- BottomPartHeight: cuint = 2 # extra height to reclaim on the bottom in borderless mode
- LeftPartWidth: cuint = 2 # extra width to reclaim on the left in borderless mode
- StaticGravity = 10
- NetMoveResizeX = 1 shl 8
- NetMoveResizeY = 1 shl 9
- NetMoveResizeWidth = 1 shl 10
- NetMoveResizeHeight = 1 shl 11
- NetMoveResizeSourceApp = 1 shl 12
- proc XOpenDisplay(name: cstring): Display {.importc, cdecl.}
- proc XCloseDisplay(d: Display) {.importc, cdecl.}
- proc XDefaultScreen(d: Display): cint {.importc, cdecl.}
- proc XBlackPixel(d: Display, screen: cint): culong {.importc, cdecl.}
- proc XRootWindow(d: Display, screen: cint): Window {.importc, cdecl.}
- proc XCreateWindow(d: Display, parent: Window, x, y: cint,
- width, height, borderWidth: cuint, depth: cint,
- class: cuint, visual: pointer,
- valuemask: culong, attrs: ptr XSetWindowAttributes): Window {.importc, cdecl.}
- proc XDestroyWindow(d: Display, w: Window) {.importc, cdecl.}
- proc XStoreName(d: Display, w: Window, name: cstring) {.importc, cdecl.}
- proc XMapWindow(d: Display, w: Window) {.importc, cdecl.}
- proc XNextEvent(d: Display, event: ptr XEvent) {.importc, cdecl.}
- proc XSelectInput(d: Display, w: Window, mask: clong) {.importc, cdecl.}
- proc XInternAtom(d: Display, atomName: cstring, onlyIfExists: cint): Atom {.importc, cdecl.}
- proc XSetWMProtocols(d: Display, w: Window, protocols: ptr Atom, count: cint): cint {.importc, cdecl.}
- proc XSendEvent(d: Display, w: Window, propagate: cint, eventMask: clong,
- event: ptr XEvent): cint {.importc, cdecl.}
- proc XSync(d: Display, discardEvents: cint): cint {.importc, cdecl.}
- proc XChangeProperty(d: Display, w: Window, property: Atom, typ: Atom,
- format: cint, mode: cint, data: pointer, nelements: cint): cint {.importc, cdecl.}
- proc XFlush(d: Display): cint {.importc, cdecl.}
- proc XTranslateCoordinates(d: Display, srcW, destW: Window, srcX, srcY: cint,
- destXReturn, destYReturn: ptr cint, childReturn: ptr Window): cint {.importc, cdecl.}
- proc sendRootClientMessage(display: Display, win: Window, root: Window,
- messageType: Atom, d0, d1, d2, d3, d4: clong) =
- var msg: XClientMessageEvent
- msg.theType = ClientMessage
- msg.send_event = 1
- msg.display = display
- msg.window = win
- msg.message_type = messageType
- msg.format = 32
- msg.data[0] = d0
- msg.data[1] = d1
- msg.data[2] = d2
- msg.data[3] = d3
- msg.data[4] = d4
- discard XSendEvent(display, root, 0,
- (SubstructureRedirectMask or SubstructureNotifyMask).clong,
- cast[ptr XEvent](addr msg))
- proc setAlwaysOnTop(display: Display, win: Window, root: Window) =
- let netWmState = XInternAtom(display, "_NET_WM_STATE", 0)
- let netWmStateAbove = XInternAtom(display, "_NET_WM_STATE_ABOVE", 0)
- sendRootClientMessage(display, win, root, netWmState,
- NET_WM_STATE_ADD.clong, netWmStateAbove.clong, 0, 1, 0)
- proc moveResizeAbsolute(display: Display, win: Window, root: Window,
- x, y: cint, width, height: cuint) =
- # Uses the EWMH _NET_MOVERESIZE_WINDOW request, which the window manager
- # interprets in true absolute screen coordinates -- unlike XMoveResizeWindow,
- # which operates relative to the window's immediate parent (the WM's own
- # decoration frame, once reparented), causing drift if used directly here.
- let atom = XInternAtom(display, "_NET_MOVERESIZE_WINDOW", 0)
- let flags = (StaticGravity or NetMoveResizeX or NetMoveResizeY or
- NetMoveResizeWidth or NetMoveResizeHeight or NetMoveResizeSourceApp).clong
- sendRootClientMessage(display, win, root, atom,
- flags, x.clong, y.clong, width.clong, height.clong)
- proc getRootPosition(display: Display, win: Window, root: Window): (cint, cint) =
- var x, y: cint
- var child: Window
- discard XTranslateCoordinates(display, win, root, 0, 0, addr x, addr y, addr child)
- (x, y)
- proc setDecorations(display: Display, win: Window, root: Window, motifHints: Atom,
- visible: bool, curX, curY: cint) =
- var hints: MwmHints
- hints.flags = MWM_HINTS_DECORATIONS.culong
- hints.decorations = (if visible: 1.culong else: 0.culong)
- discard XChangeProperty(display, win, motifHints, motifHints, 32,
- PropModeReplace, addr hints, 5)
- discard XFlush(display)
- if visible:
- moveResizeAbsolute(display, win, root, curX + LeftPartWidth.cint, curY + TopPartHeight.cint,
- WindowSize, WindowSize)
- else:
- moveResizeAbsolute(display, win, root, curX - LeftPartWidth.cint, curY - TopPartHeight.cint,
- WindowSize + LeftPartWidth + RightPartWidth,
- WindowSize + TopPartHeight + BottomPartHeight)
- proc main() =
- let display = XOpenDisplay(nil)
- if cast[pointer](display) == nil:
- quit("Cannot open X display")
- let screen = XDefaultScreen(display)
- let black = XBlackPixel(display, screen)
- let root = XRootWindow(display, screen)
- var attrs: XSetWindowAttributes
- attrs.background_pixel = black
- let win = XCreateWindow(
- display, root,
- InitialX, InitialY,
- WindowSize, WindowSize,
- 1,
- 24,
- InputOutput.cuint,
- nil,
- CWBackPixel.culong,
- addr attrs
- )
- XStoreName(display, win, "Distraction Cover")
- XSelectInput(display, win, (ExposureMask or ButtonPressMask or StructureNotifyMask).clong)
- var wmDeleteMessage = XInternAtom(display, "WM_DELETE_WINDOW", 0)
- discard XSetWMProtocols(display, win, addr wmDeleteMessage, 1)
- let motifHints = XInternAtom(display, "_MOTIF_WM_HINTS", 0)
- XMapWindow(display, win)
- discard XSync(display, 0)
- setAlwaysOnTop(display, win, root)
- var trackedX: cint = InitialX
- var trackedY: cint = InitialY
- var decorationsVisible = true
- var lastClickTime: culong = 0
- var event: XEvent
- var running = true
- while running:
- XNextEvent(display, addr event)
- let eventType = cast[ptr cint](addr event)[]
- if eventType == ConfigureNotify:
- let (x, y) = getRootPosition(display, win, root)
- trackedX = x
- trackedY = y
- elif eventType == ButtonPress:
- let be = cast[ptr XButtonEvent](addr event)
- if be.button == Button1:
- let delta = be.time - lastClickTime
- if lastClickTime != 0 and delta < DoubleClickThresholdMs:
- decorationsVisible = not decorationsVisible
- setDecorations(display, win, root, motifHints, decorationsVisible, trackedX, trackedY)
- lastClickTime = 0
- else:
- lastClickTime = be.time
- elif eventType == ClientMessage:
- let cm = cast[ptr XClientMessageEvent](addr event)
- if Atom(cm.data[0]) == wmDeleteMessage:
- running = false
- XDestroyWindow(display, win)
- XCloseDisplay(display)
- main()
Advertisement
Add Comment
Please, Sign In to add comment