Snippets

This page shows small snippets that might be useful. Without further instructions they just need to be copied into the config of subtle.

Alt-Tab

This cycles through windows of view

Numbers: on /off 1 grab "A-Tab" do |c|
 2    sel     = 0
 3    clients = Subtlext::View[:current].clients
 4 
 5    clients.each_index do |idx|
 6      if(clients[idx].id == c.id)
 7        sel = idx + 1 if(idx < clients.size - 1)
 8      end
 9    end
10 
11   clients[sel].focus
12 end

Gravity tiling

Tiles windows vertically that share a gravity.

Numbers: on /off 1 on :tile do
 2   clients = Subtlext::View.current.clients
 3   screen  = Subtlext::Screen.current
 4 
 5   assoc = {}
 6 
 7   clients.each do |c|
 8     begin
 9       assoc[c.gravity.id] << c rescue assoc[c.gravity.id] = [ c ]
10     rescue StandardError
11       # Startup errors
12     end
13   end
14 
15   assoc.each do |k, v|
16     g      = Subtlext::Gravity[k]
17     border = 2 #< Currently hardcoded
18 
19     # Calculate gravity
20     x, y, w, h = g.geometry_for(screen)
21     width      = w / v.size
22     pos        = x
23 
24     v.each do |c|
25       c.resize   = false
26       c.geometry = [ pos, y, width - 2 * border, h - 2 * border ]
27       pos += width
28     end
29   end
30 end

Extend view

Numbers: on /off 1 require "subtle/subtlext" 
 2 
 3 STORE ||= {}
 4 
 5 module Subtlext
 6   class View
 7     def method_missing(meth, *args)
 8       STORE[self.name] = { } unless(STORE.has_key?(self.name))
 9 
10       if(meth.to_s.end_with?("="))
11         meth = meth.to_s.chop.to_sym
12 
13         STORE[self.name][meth] = args[0]
14       else
15         STORE[self.name][meth]
16       end
17     end
18   end
19 end

Finally make some use of this like following hook:

Numbers: on /off1 on :view_jump do |v|
2   v.visits += 1 rescue v.visits = 1
3   puts "View %s, %d visits" % [ v.name, v.visits ]
4 end

Focus gravities

Focus window a specific gravities on view.

Numbers: on /off 1 {
 2   "KP_7" => :top_left,    "KP_8" => :top,    "KP_9" => :top_right,
 3   "KP_4" => :left,        "KP_5" => :center, "KP_6" => :right,
 4   "KP_1" => :bottom_left, "KP_2" => :bottom, "KP_3" => :bottom_right
 5 }.each do |k, v|
 6   grab "A-C-" + k, lambda {
 7     c = Subtlext::View.current.clients.select { |c|
 8       c.gravity.name.to_sym == v
 9     }
10 
11     c.first.focus unless(c.empty?)
12   }
13 end

Move windows

This snippet adds nine grabs to move windows on the fly to nine defined views. It uses tagging for this, creates tags based on the view names and applies them when needed.

Numbers: on /off 1 on :start do
 2   # Create missing tags
 3   views = Subtlext::View.all.map { |v| v.name }
 4   tags  = Subtlext::Tag.all.map { |t| t.name }
 5 
 6   views.each do |v|
 7     unless(tags.include?(v))
 8       t = Subtlext::Tag.new(v)
 9       t.save
10     end
11   end
12 end
13 
14 # Add nine C-< number> grabs
15 (1..9).each do |i|
16  grab "C-%d" % [ i ] do |c|
17    views = Subtlext::View.all
18    names = views.map { |v| v.name }
19 
20    # Sanity check
21    if(i <= views.size)
22      # Tag client
23      tags = c.tags.reject { |t| names.include?(t.name) or "default" == t.name }
24      tags << names[i - 1]
25 
26      c.tags = tags
27 
28      # Tag view
29      views[i - 1].tag(names[i - 1])
30    end
31  end
32 end

Current view

This snippet works similar to the previous, it adds tags based on the view names. When there is an untagged window (a window with the default tag only) it adds the name of the current view as tag, which effectively moves the window to the current view.

Numbers: on /off 1 on :start do
 2   # Create missing tags
 3   views = Subtlext::View.all.map { |v| v.name }
 4   tags  = Subtlext::Tag.all.map { |t| t.name }
 5 
 6   views.each do |v|
 7     unless(tags.include?(v))
 8       t = Subtlext::Tag.new(v)
 9       t.save
10     end
11   end
12 end
13 
14 # Assign tags to clients
15 on :client_create do |c|
16   view = Subtlext::View.current
17   tags = c.tags.map { |t| t.name }
18 
19   # Add tag to view
20   view.tag(view.name) unless(view.tags.include?(view.name))
21 
22   # Exclusive for clients with default tag only
23   if(tags.include?("default") and 1 == tags.size)
24     c.tags = [ view.name ]
25   end
26 end