Skip to content

Instantly share code, notes, and snippets.

@pachacamac
Last active July 29, 2017 08:44
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save pachacamac/3fb0ae7272cebd4b40cb to your computer and use it in GitHub Desktop.
Save pachacamac/3fb0ae7272cebd4b40cb to your computer and use it in GitHub Desktop.
simple tiling script
#!/usr/bin/env ruby
# DESCRIPTION:
# This is a script to rearrange your windows like this:
# _________________________ _________________________
# | _________ | x| | | major x| minor x|
# | | major x |__| | | | |____________|
# | | | |_____| | --> | | minor x|
# | |_________| | ______ | | |____________|
# | |______|| x|| | | minor x|
# |_________________|______|| |____________|____________|
#
# It gives you some benefits of tiling window managers without
# forcing you to leave your cozy floating window manager behind.
#
# INSTALL:
# 1) apt-get install libx11-dev libglib2.0-dev libxmu-dev
# 2) gem install ruby-wmctrl
# 3) add keyboard shortcut with something like: rvm-shell -c 'ruby /path/to/tiler.rb'
#
# USAGE:
# When you press the configured keyboard shortcut, tiler rearranges your windows so that
# - The active window takes the left half of the screen
# - The remaining non minimized, non blacklisted windows are spread out over the rest of the screen
require 'wmctrl'
# don't consider windows that match any of these criterias
window_blacklist = [
->(w){w.title == 'Buddy List' && w.wm_class == 'Pidgin.Pidgin'}
]
# don't consider minimized windows and taskbars and such
state_blacklist = ['_NET_WM_STATE_HIDDEN', '_NET_WM_STATE_SKIP_PAGER', '_NET_WM_STATE_SKIP_TASKBAR', '_NET_WM_STATE_STICKY']
desktop = WMCtrl.instance.desktops.find{|e| e.current} #only consider active desktop
wa_x, wa_y, wa_w, wa_h = desktop.workarea
windows = WMCtrl.instance.windows.
select{|win|
win.desktop == desktop.id &&
(win.state & state_blacklist).empty? &&
!window_blacklist.any?{|condition| condition[win]}
}
active, rest = windows.find(&:active), windows.reject(&:active)
def move(window, x, y, w, h)
id = window.class == WMCtrl::Window ? window.id : window
WMCtrl.instance.action_window(id, :change_state, 'remove', 'fullscreen')
WMCtrl.instance.action_window(id, :change_state, 'remove', 'maximized_horz', 'maximized_vert')
WMCtrl.instance.action_window(id, :move_resize, 0, x, y, w, h)
end
l,r,t,b = active.frame_extents
move(active, wa_x, wa_y, wa_w / 2 - l - r, wa_h - t - b) # move active window to left half of the screen
# spread remaining visible, not blacklisted windows to the remaining space
rest.each_with_index do |win, i|
l,r,t,b = win.frame_extents
move(win,
wa_x + wa_w / 2,
wa_y + (wa_h / rest.size) * i,
wa_w / 2 - l - r,
wa_h / rest.size - t - b
)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment