Only managed windows have corresponding window nodes. Besides the generic tree node properties (i.e. :type
, :parent
and :children
), a window object currently only have two extra properties: :hwnd
and :tags
.
:hwnd
property
The :hwnd
property is the window's native Win32 window handle, which can be passed to low-level Win32 functions. For example, we can call ShowWindow
to hide/show a window in the REPL:
Welcome to Jwno REPL!
[127.0.0.1:9999]:1: (use jw32/_winuser)
# Put this line (without the prompt, of course) into the REPL,
# and switch to the managed window you want to manipulate while
# the REPL is sleeping
[127.0.0.1:9999]:2: (ev/sleep 3) (def win (:get-current-window (get-in jwno/context [:window-manager :root])))
# Be careful when doing this, you may lose track of the hidden
# window. Use some window you can throw away, e.g. an empty
# Notepad window. It's a fun trick to play with though 😜
[127.0.0.1:9999]:3: (ShowWindow (in win :hwnd) SW_HIDE)
# Do this to get your window back
[127.0.0.1:9999]:4: (ShowWindow (in win :hwnd) SW_SHOW)
The ev/sleep
trick is something I use when debugging Jwno itself. Given the power of the REPL, you can certainly find other ways to retrieve a window node.
:tags
property
The next window property we'll talk about is :tags
. It's a Janet table that stores any user-defined properties for that window. For example, you can mark your favorite windows when they're created:
(:add-hook (in jwno/context :hook-manager) :window-created
(fn [win _uia _exe _desktop]
(when (is-my-favorite-window? win)
(put (in win :tags) :favorite true))))
And then pull them up by checking their :tags
when using the :summon
command:
(:call-command (in jwno/context :command-manager)
:summon
(fn [win]
(def tags (in win :tags))
(= true (in tags :favorite))))
Note that certain tag names are used by Jwno to layout the windows, you can set them to the values you prefer, but cannot use these names for other purposes:
Tag Name | Description |
---|---|
:anchor | Used to determine where the window should be placed when it does not fill the whole frame. Can be one of :center , :top-left , :top , :top-right , :left , :right , :bottom-left , :bottom , :bottom-right . It's only meaningful when :no-expand or :no-resize is specified, or when the window can not be resized. |
:forced | Whether this window is managed forcibly. |
:frame | A specific frame to put this window into. This overrides the default window placement rules, and can only be set in the :window-created hook. |
:margin and :margins | Used to specify margins (gaps) around the window, when fitting it into a frame. You can specify non-uniform margins in :margins like this: (put tags :margins {:left 10 :top 20 :right 30 :bottom 40}) , and they will override the value in :margin . |
:no-expand | Tell Jwno not to enlarge a window when putting it into a frame (but shrinking can still happen). Can be used when dealing with modal dialog boxes, so that they fit nicely inside the frame, without covering their owner windows. |
:no-resize | Tell Jwno not to resize a window when taking it under management. |
:swp-flags | Tell Jwno to set these flags when calling SetWindowPos . This is mainly used to specify SWP_NOSENDCHANGING , to forcibly bypass window size limits when resizing. See the relevant section in Cookbook for an example and some explanation. |
All these tags, except :frame
, take effect when retiling or transforming a window. For example, you can experiment with the :margin
setting in the REPL, like this:
(put (in win :tags) :margin 100) # Or any other value you prefer
(:call-command (in jwno/context :command-manager) :retile)