Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions docs/wormc.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,25 @@ Describes the layout of the frame *on the left side*. This is a comma separated
- C for close button
- M for maximize button
- I for iconify/minimize button
eg: `wormc frame-left 'T;C;M'
eg: `wormc frame-left 'T;C;M'`
### `frame-center(string)` / `frame-right(string)`
same as frame-left, but for the center and right parts of a frame window.
### `button-size(int)`
The size (both width and height) of all window buttons. The window buttons don't have to nessecarily be perfect squares. You can use the larger dimension and the rest of the window will just not render. Eg: `wormc button-size 14`
### `button-offset(x, y)`
The offset at both the x and y positions at which buttons on the titlebar (M, C) are located, for example `wormc button-offset 10 10`.
### `maximize-path / close-path (string)`
Full path to the maximize and close buttons, respectively. If this is unspecified or the value is invalid, then that part will skip rendering. Eg `wormc maximize-path ~/.config/worm/max.png`.
### `close-active-path(string) / close-inactive-path(string)`
Full path to the active and inactive maximize buttons, respectively. If unspecified or invalid the button simply won't render in that state.

Ex. `wormc close-active-path ~/.config/worm/close-active.png`.
### `maximize-active-path(string) / maximize-inactive-path(string)`
Full path to the active and inactive maximize buttons, respectively. See [close-active-path](#close-active-pathstring--close-inactive-pathstring).

Ex.`wormc maximize-inactive-path ~/.config/worm/max-inactive.png`.
### `minimize-active-path(string) / minimize-inactive-path(string)`
Full path to the active and inactive minimize buttons, respectively. See [close-active-path](#close-active-pathstring--close-inactive-pathstring).

Ex. `wormc minimize-active-path ~/.config/worm/min-active.png`.
### `root-menu(string)`
Sets path to the root menu. If this file is valid, upon right-clicking the root window it's executed (assumed to be an executable file). Eg `wormc root-menu ~/worm/examples/jgmenu_run`.
### `decoration-disable(string)`
Expand Down
9 changes: 6 additions & 3 deletions src/atoms.nim
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,12 @@ type
IpcButtonOffset = "WORM_IPC_BUTTON_OFFSET",
IpcButtonSize = "WORM_IPC_BUTTON_SIZE",
IpcRootMenu = "WORM_IPC_ROOT_MENU",
IpcClosePath = "WORM_IPC_CLOSE_PATH",
IpcMaximizePath = "WORM_IPC_MAXIMIZE_PATH",
IpcMinimizePath = "WORM_IPC_MINIMIZE_PATH",
IpcCloseActivePath = "WORM_IPC_CLOSE_ACTIVE_PATH",
IpcCloseInactivePath = "WORM_IPC_CLOSE_INACTIVE PATH",
IpcMaximizeActivePath = "WORM_IPC_MAXIMIZE_ACTIVE_PATH",
IpcMaximizeInactivePath = "WORM_IPC_MAXIMIZE_INACTIVE_PATH",
IpcMinimizeACtivePath = "WORM_IPC_MINIMIZE_ACTIVE_PATH",
IpcMinimizeInactivePath = "WORM_IPC_MINIMIZE_INACTIVE_PATH",
IpcMaximizeClient = "WORM_IPC_MAXIMIZE_CLIENT",
IpcMinimizeClient = "WORM_IPC_MINIMIZE_CLIENT",
IpcDecorationDisable = "WORM_IPC_DECORATION_DISABLE"
Expand Down
63 changes: 51 additions & 12 deletions src/events/clientmessage.nim
Original file line number Diff line number Diff line change
Expand Up @@ -440,42 +440,81 @@ proc handleClientMessage*(self: var Wm; ev: XClientMessageEvent) =
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcClosePath]:
elif ev.data.l[0] == clong self.ipcAtoms[IpcCloseActivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcClosePath])
IpcCloseActivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing close path to " & $fontList[0]
self.config.closePath = $fontList[0]
log "Changing active close path to " & $fontList[0]
self.config.closePaths[bsActive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcMaximizePath]:
elif ev.data.l[0] == clong self.ipcAtoms[IpcCloseInactivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcMaximizePath])
IpcCloseInactivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing maximize path to " & $fontList[0]
self.config.maximizePath = $fontList[0]
log "Changing inactive close path to " & $fontList[0]
self.config.closePaths[bsInactive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcMinimizePath]:
elif ev.data.l[0] == clong self.ipcAtoms[IpcMaximizeActivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcMinimizePath])
IpcMaximizeActivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing minimize path to " & $fontList[0]
self.config.minimizePath = $fontList[0]
log "Changing active maximize path to " & $fontList[0]
self.config.maximizePaths[bsActive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcMaximizeInactivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcMaximizeInactivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing inactive maximize path to " & $fontList[0]
self.config.maximizePaths[bsInactive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcMinimizeActivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcMinimizeActivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing active minimize path to " & $fontList[0]
self.config.minimizePaths[bsActive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
elif ev.data.l[0] == clong self.ipcAtoms[IpcMinimizeInactivePath]:
var fontProp: XTextProperty
var fontList: ptr UncheckedArray[cstring]
var n: cint
discard self.dpy.XGetTextProperty(self.root, addr fontProp, self.ipcAtoms[
IpcMinimizeInactivePath])
let err = self.dpy.XmbTextPropertyToTextList(addr fontProp, cast[
ptr ptr cstring](addr fontList), addr n)
log "Changing inactive minimize path to " & $fontList[0]
self.config.minimizePaths[bsInactive] = $fontList[0]
if err >= Success and n > 0 and fontList != nil and fontList[0] != nil:
XFreeStringList cast[ptr cstring](fontList)
discard XFree fontProp.value
Expand Down
6 changes: 5 additions & 1 deletion src/types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ type
lyFloating, lyTiling
FramePart* = enum
fpTitle, fpClose, fpMaximize, fpMinimize
ButtonState* = enum
bsActive, bsInactive
Geometry* = object
x*, y*: int
width*, height*: uint
Expand Down Expand Up @@ -42,7 +44,9 @@ type
frameParts*: tuple[left, center, right: seq[FramePart]]
buttonSize*: uint # always square FOR NOW
rootMenu*: string
closePath*, maximizePath*, minimizePath*: string
closePaths*: array[ButtonState, string]
maximizePaths*: array[ButtonState, string]
minimizePaths*: array[ButtonState, string]
TagSet* = array[9, bool] # distinct

proc defaultTagSet*: TagSet = [true, false, false, false, false, false, false,
Expand Down
53 changes: 30 additions & 23 deletions src/wm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,18 @@ proc renderTop*(self: var Wm; client: var Client) =
gc = self.dpy.XCreateGC(client.frame.close, 0, addr gcVal)

# discard self.dpy.XSetForeground(gc, self.config.textActivePixel)
let fp =
if self.focused.isSome and client == self.clients[self.focused.get]:
self.config.frameActivePixel
else:
self.config.frameInactivePixel
let
isFocused = self.focused.isSome and client == self.clients[self.focused.get]
fp =
if isFocused:
self.config.frameActivePixel
else:
self.config.frameInactivePixel
buttonState =
if isFocused:
bsActive
else:
bsInactive

# draw the 3 'regions' of the titlebar; left, center, right
var
Expand Down Expand Up @@ -304,7 +311,7 @@ proc renderTop*(self: var Wm; client: var Client) =

closeExists = true

if not fileExists self.config.closePath:
if not fileExists self.config.closePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.close
Expand Down Expand Up @@ -336,15 +343,15 @@ proc renderTop*(self: var Wm; client: var Client) =
buttonYOffset
)

let image = self.XCreateImage(self.config.closePath, fp, attr)
let image = self.XCreateImage(self.config.closePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.close, gc)

of fpMaximize:

maximizeExists = true

if not fileExists self.config.maximizePath:
if not fileExists self.config.maximizePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.maximize
Expand Down Expand Up @@ -376,13 +383,13 @@ proc renderTop*(self: var Wm; client: var Client) =
self.config.buttonOffset.y.cint
)

let image = self.XCreateImage(self.config.maximizePath, fp, attr)
let image = self.XCreateImage(self.config.maximizePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.maximize, gc)
of fpMinimize:
minimizeExists = true

if not fileExists self.config.minimizePath:
if not fileExists self.config.minimizePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.minimize
Expand Down Expand Up @@ -414,7 +421,7 @@ proc renderTop*(self: var Wm; client: var Client) =
self.config.buttonOffset.y.cint
)

let image = self.XCreateImage(self.config.minimizePath, fp, attr)
let image = self.XCreateImage(self.config.minimizePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.minimize, gc)
for i, part in self.config.frameParts.center:
Expand Down Expand Up @@ -444,10 +451,10 @@ proc renderTop*(self: var Wm; client: var Client) =

closeExists = true

if not fileExists self.config.closePath:
if not fileExists self.config.closePaths[buttonState]:
continue

let image = self.XCreateImage(self.config.closePath, fp, attr)
let image = self.XCreateImage(self.config.closePaths[buttonState], fp, attr)

let
btnSize = self.config.buttonSize.cint
Expand Down Expand Up @@ -497,7 +504,7 @@ proc renderTop*(self: var Wm; client: var Client) =

maximizeExists = true

if not fileExists self.config.maximizePath:
if not fileExists self.config.maximizePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.maximize
Expand Down Expand Up @@ -534,16 +541,16 @@ proc renderTop*(self: var Wm; client: var Client) =
btnYOffset
)

let image = self.XCreateImage(self.config.maximizePath, fp, attr)
let image = self.XCreateImage(self.config.maximizePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.maximize, gc)
of fpMinimize:
minimizeExists = true

if not fileExists self.config.minimizePath:
if not fileExists self.config.minimizePaths[buttonState]:
continue

let image = self.XCreateImage(self.config.minimizePath, fp, attr)
let image = self.XCreateImage(self.config.minimizePaths[buttonState], fp, attr)

let
btnSize = self.config.buttonSize.cint
Expand Down Expand Up @@ -633,10 +640,10 @@ proc renderTop*(self: var Wm; client: var Client) =

closeExists = true

if not fileExists self.config.closePath:
if not fileExists self.config.closePaths[buttonState]:
continue

let image = self.XCreateImage(self.config.closePath, fp, attr)
let image = self.XCreateImage(self.config.closePaths[buttonState], fp, attr)

let
btnXOffset = self.config.buttonOffset.x.cint
Expand Down Expand Up @@ -682,7 +689,7 @@ proc renderTop*(self: var Wm; client: var Client) =

maximizeExists = true

if not fileExists self.config.maximizePath:
if not fileExists self.config.maximizePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.maximize
Expand Down Expand Up @@ -727,13 +734,13 @@ proc renderTop*(self: var Wm; client: var Client) =
self.config.buttonOffset.y.cint
)

let image = self.XCreateImage(self.config.maximizePath, fp, attr)
let image = self.XCreateImage(self.config.maximizePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.maximize, gc)
of fpMinimize:
minimizeExists = true

if not fileExists self.config.minimizePath:
if not fileExists self.config.minimizePaths[buttonState]:
continue

discard self.dpy.XMapWindow client.frame.minimize
Expand Down Expand Up @@ -778,7 +785,7 @@ proc renderTop*(self: var Wm; client: var Client) =
self.config.buttonOffset.y.cint
)

let image = self.XCreateImage(self.config.minimizePath, fp, attr)
let image = self.XCreateImage(self.config.minimizePaths[buttonState], fp, attr)

self.XPutImage(image, client.frame.minimize, gc)

Expand Down
27 changes: 18 additions & 9 deletions src/wormc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,24 @@ proc main() =
of "root-menu":
dpy.sendStrPrep(ipcAtoms[IpcRootMenu], params[i+1])
data = formatMess ipcAtoms[IpcRootMenu]
of "close-path":
dpy.sendStrPrep(ipcAtoms[IpcClosePath], params[i+1])
data = ipcAtoms[IpcClosePath].formatMess()
of "maximize-path":
dpy.sendStrPrep(ipcAtoms[IpcMaximizePath], params[i+1])
data = ipcAtoms[IpcMaximizePath].formatMess()
of "minimize-path":
dpy.sendStrPrep(ipcAtoms[IpcMinimizePath], params[i+1])
data = ipcAtoms[IpcMinimizePath].formatMess()
of "close-active-path":
dpy.sendStrPrep(ipcAtoms[IpcCloseActivePath], params[i+1])
data = ipcAtoms[IpcCloseActivePath].formatMess()
of "close-inactive-path":
dpy.sendStrPrep(ipcAtoms[IpcCloseInactivePath], params[i+1])
data = ipcAtoms[IpcCloseInactivePath].formatMess()
of "maximize-active-path":
dpy.sendStrPrep(ipcAtoms[IpcMaximizeActivePath], params[i+1])
data = ipcAtoms[IpcMaximizeActivePath].formatMess()
of "maximize-inactive-path":
dpy.sendStrPrep(ipcAtoms[IpcMaximizeInactivePath], params[i+1])
data = ipcAtoms[IpcMaximizeInactivePath].formatMess()
of "minimize-active-path":
dpy.sendStrPrep(ipcAtoms[IpcMinimizeActivePath], params[i+1])
data = ipcAtoms[IpcMinimizeActivePath].formatMess()
of "minimize-inactive-path":
dpy.sendStrPrep(ipcAtoms[IpcMinimizeInactivePath], params[i+1])
data = ipcAtoms[IpcMinimizeInactivePath].formatMess()
of "decoration-disable":
dpy.sendStrPrep(ipcAtoms[IpcDecorationDisable], params[i+1])
data = ipcAtoms[IpcDecorationDisable].formatMess()
Expand Down