Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # coding: utf-8
- #-----------------------------------------------------------------------------
- # New API
- #-----------------------------------------------------------------------------
- ## Clients get extended with this module, because apparently I can't change
- ## the Subtlext::Client class
- module ClientWrapper
- def self.make_setter *args
- args.each do |arg|
- class_eval "def #{arg} x
- self.#{arg} = x
- end"
- end
- end
- def self.make_toggle_setter *args
- args.each do |arg|
- class_eval "def #{arg} x
- toggle_#{arg} if x != is_#{arg}?
- end"
- end
- end
- ## Subtle provides things like `c.gravity = :foo` but that won't work if
- ## the client is instance_eval'd into a block, so this provides versions
- ## that do the assignment so you can say things like `gravity :foo`
- make_setter :flags, :geometry, :gravity, :tags
- ## Subtle only provides things like `is_float?` and `toggle_float`, so this
- ## creates some nice wrappers so you can say things like `c.float true`
- ## rather than `c.toggle_float unless c.is_float?`
- make_toggle_setter :borderless, :fixed, :float, :full,
- :resize, :stick, :urgent, :zaphod
- ## Needed so assigning the gravity sets it on all the client's views rather
- ## than only the current one
- def gravity= x
- if Symbol === x
- views.each { |v| super v => x }
- else
- super
- end
- end
- ## Returns true if the client would be matched by the argument `x`
- ##
- ## It uses the same matching rules as `match foo` inside a tag, with the
- ## sole exception that strings are exact matches rather than treated as
- ## regexps
- def matches? x
- case x
- when String
- x == instance or x == klass
- when Regexp
- x.match(instance) or x.match(klass)
- when Hash
- x.all? do |k, v|
- k = (k == :class) ? klass
- : send(k)
- (String === v) ? v == k
- : v.match(k)
- end
- else
- raise TypeError
- end
- end
- end
- # TODO: better way to access the old stuff...
- $self = self
- alias old_view view
- alias old_tag tag
- class Tag
- def initialize name, &f
- @clients = []
- @on_match = []
- ## Special DSL sugar that lets you pass in a block with no arguments
- if block_given?
- if f.arity == 0
- instance_eval &f
- else
- f.call self
- end
- end
- # TODO: very hacky
- unless Symbol === name
- ## Needed because `$self.old_tag` evaluates the block's body in a
- ## different environment
- _clients = @clients
- _gravity = @gravity
- _on_match = @on_match
- $self.old_tag name do
- _clients.each { |x| match x }
- gravity _gravity if _gravity
- on_match do |c|
- ## Makes the methods in `ClientWrapper` available to the client
- # TODO: potentially slow, maybe I can cache it somehow?
- c.extend ClientWrapper
- _on_match.each { |x| x.call c }
- end
- end
- end
- end
- def on x, &f
- if x == :match
- ## DSL sugar
- @on_match << (f.arity == 0 ? lambda { |c| c.instance_eval &f } : f)
- else
- raise NoMethodError, String(x)
- end
- end
- ## Sets the gravity of either the entire view, or an individual client
- ## within the view
- def gravity g, x=nil
- if x
- @clients << x
- @on_match << lambda { |c| c.gravity = g if c.matches? x }
- else
- @gravity = g
- end
- end
- ## Matches a client and optionally calls a block, passing it the client
- def client x, &f
- @clients << x
- if block_given?
- ## DSL sugar
- @on_match << (f.arity == 0 ? lambda { |c| c.instance_eval &f if c.matches? x }
- : lambda { |c| yield c if c.matches? x })
- end
- end
- end
- class View < Tag
- def self.attr_maker x
- x.each do |k, v|
- class_eval "def #{k} x
- raise TypeError if Symbol === @name
- @#{k} #{v} x
- end"
- end
- end
- attr_maker icon: "<<", tag: "<<", dynamic: "=", icon_only: "="
- def initialize name, &f
- @name = name
- @icon = []
- @tag = [name]
- ## Calls the Tag class's initialize
- super
- # TODO: very hacky
- if Symbol === name
- if name == :current
- =begin
- super "default" do
- f.call self
- on :match do
- self.tags = [ Subtlext::View.current.name ]
- end
- end
- $self.old_tag "default" do
- on_match
- end
- =end
- $self.on :client_create do |c|
- ## Checks to see if the client is tagged with "default" only
- if c.tags.size == 1 and c.tags[0].name == "default"
- # TODO: code duplication
- # TODO: ew, having to extend it just for the sake of matches? ...
- c.extend ClientWrapper
- ## Checks to see if the client matches any of the rules
- if @clients.any? { |x| c.matches? x }
- c.tags = [ Subtlext::View.current.name ]
- c.gravity = @gravity if @gravity
- # TODO: code duplication
- @on_match.each { |x| x.call c }
- end
- end
- end
- else
- raise NoMethodError, String(name)
- end
- else
- ## This is needed because views can't have more than one
- ## `match` method, so we have to union them together into
- ## a single `match`
- _tag = Regexp.union @tag
- _icon = @icon
- _dynamic = @dynamic
- _icon_only = @icon_only
- $self.old_view name do
- match _tag
- _icon.each { |x| icon x }
- dynamic true if _dynamic
- icon_only true if _icon_only
- end
- end
- end
- end
- ## These two are just to make it a bit shorter and cleaner looking
- def view name, &f
- View.new(name, &f)
- end
- def tag name, &f
- Tag.new(name, &f)
- end
- #-----------------------------------------------------------------------------
- # Options
- #-----------------------------------------------------------------------------
- ## Window screen border snapping
- set :snap, 10
- ## Default starting gravity for windows. Comment out to use gravity of
- ## currently active client
- set :gravity, :g100_g
- ## Make transient windows urgent
- set :urgent, false
- ## Honor resize size hints globally
- set :resize, false
- #-----------------------------------------------------------------------------
- # Screens
- #-----------------------------------------------------------------------------
- screen 1 do
- top [ :title , :keychain , :spacer ,
- :center , :views , :center ,# :layout ,
- :tray , :separator , :sublets , :clock ]
- bottom [ ]
- end
- #-----------------------------------------------------------------------------
- # Styles
- #-----------------------------------------------------------------------------
- style :all do
- # Font string either take from e.g. xfontsel or use xft
- font "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"
- padding_bottom 1
- end
- style :views do
- foreground "#656565"
- padding_left 5
- padding_right 5
- style :focus do
- foreground "#fecf35"
- end
- style :urgent do
- foreground "#ff9800"
- end
- # Style for occupied views (views with clients)
- style :occupied do
- foreground "#b8b8b8"
- end
- end
- style :sublets do
- foreground "#bbbbbb"
- style :clock do
- icon "#000000"
- padding_right 10
- padding_left 0
- end
- end
- style :separator do
- separator "ǁ"
- foreground "#222222"
- end
- style :title do
- foreground "#fecf35"
- padding_left 10
- end
- style :clients do
- active "#00ff00", 1
- inactive "#000000", 1
- width 90
- end
- # TODO: will be obsolete eventually
- style :subtle do
- panel "#000000"
- end
- #-----------------------------------------------------------------------------
- # Grabs
- #-----------------------------------------------------------------------------
- #def view_find_visible
- # # get the next view from the iterator
- # view = yield Subtlext::View.current
- # # mostly equivalent to `loop do`
- # while true
- # # view has visible clients or is nil, so we can return it
- # if not view.clients.empty? or !view
- # return view
- # else
- # # get the next view from the iterator
- # view = yield view
- # end
- # end
- #end
- def view_find_visible
- views = Subtlext::View.all
- index = yield views.index Subtlext::View.current
- while true
- view = views[index % views.size]
- # if view has clients, we can return it
- unless view.clients.empty?
- return view
- else
- index = yield index
- end
- end
- end
- grab "A-Tab" do
- view_find_visible { |x| x + 1 }.jump
- #view_find_visible { |x| x.next or Subtlext::View[0] }.jump
- end
- grab "A-S-Tab" do
- view_find_visible { |x| x - 1 }.jump
- #view_find_visible { |x| x.prev or Subtlext::View[-1] }.jump
- end
- # Force reload of config and sublets
- grab "M-C-r", :SubtleReload
- grab "M-C-S-r", :SubtleRestart
- grab "M-B1", :WindowMove
- grab "M-B3", :WindowResize
- grab "M-f", :WindowFloat
- grab "M-r", :WindowRaise
- grab "M-l", :WindowLower
- # Select windows
- grab "M-Left", :WindowLeft
- grab "M-Down", :WindowDown
- grab "M-Up", :WindowUp
- grab "M-Right", :WindowRight
- grab "M-c", :WindowKill
- grab "M-Return", "xfce4-terminal" #"urxvt"
- grab "Print", "xfce4-screenshooter -s Screenshots -w -m"
- grab "M-Print", "xfce4-screenshooter -s Screenshots -f"
- grab "M-v", "volume"
- # Assign gravities
- grab "M-KP_7", [ :g50_ul ]
- grab "M-KP_9", [ :g50_ur ]
- grab "M-KP_5", [ :g100_g ]
- grab "M-KP_1", [ :g50_ll ]
- grab "M-KP_3", [ :g50_lr ]
- # M 1-9 to send a window to that view
- (1..9).each do |i|
- grab "M-#{i}" do |c|
- views = Subtlext::View.all
- grav = c.gravity
- if i <= views.size
- view = views[i - 1]
- c.tags = [ view.name ]
- c.gravity = { view => grav }
- end
- end
- end
- #-----------------------------------------------------------------------------
- # Gravities
- #-----------------------------------------------------------------------------
- ## Grid15
- gravity :g15_l, [ 0, 0, 15, 100 ], :vert
- gravity :g15_r, [ 15, 0, 85, 100 ], :vert
- gravity :g15_ul, [ 0, 0, 15, 50 ]
- gravity :g15_ur, [ 15, 0, 85, 50 ]
- gravity :g15_ll, [ 0, 50, 15, 50 ]
- gravity :g15_lr, [ 15, 50, 85, 50 ]
- ## Grid50
- gravity :g50_c, [ 25, 25, 50, 50 ]
- gravity :g50_ul, [ 0, 0, 50, 50 ]
- gravity :g50_ur, [ 50, 0, 50, 50 ]
- gravity :g50_ll, [ 0, 50, 50, 50 ]
- gravity :g50_lr, [ 50, 50, 50, 50 ]
- ## Grid60
- gravity :g60_l, [ 0, 0, 60, 100 ], :vert
- gravity :g60_r, [ 60, 0, 40, 100 ], :vert
- ## Grid100
- gravity :g100_g, [ 0, 0, 100, 100 ], :horz #:grid
- gravity :g100_c, [ 0, 0, 100, 100 ]
- ## Chrome
- gravity :chrome_l, [ 0, 0, 17, 100 ]
- gravity :chrome_r, [ 17, 0, 83, 100 ]
- #-----------------------------------------------------------------------------
- # Views
- #-----------------------------------------------------------------------------
- =begin
- move_to_current = lambda do |c|
- c.on :match do
- self.tags = [ Subtlext::View.current.name ]
- end
- end
- client "Steam.exe", &move_to_current
- client "xfrun4" do
- move_to_current self
- gravity :g50_c
- float true
- end
- =end
- view :current do
- client "Steam.exe"
- client "xfrun4" do
- gravity :g50_c
- float true
- end
- end
- view "stat" do
- gravity :g50_ul, "xfce4-taskmanager"
- gravity :g50_ll, "transmission-gtk"
- gravity :g50_lr, "pavucontrol"
- end
- view "www" do
- client "Firefox"
- client class: "Firefox", role: "browser" do
- borderless true
- end
- end
- view "text" do
- gravity :g60_l, "gedit"
- gravity :g60_r, "xfce4-terminal"
- end
- view "chat" do
- client "Pidgin"
- gravity :g15_ul, instance: "Pidgin", role: "buddy_list"
- gravity :g15_ur, instance: "Pidgin", role: "conversation"
- gravity :g15_ll, instance: "Steam.exe", name: "Friends"
- gravity :g15_lr, instance: "Steam.exe", name: /^.+\ -\ Chat$/
- end
- view "5" do
- tag "default"
- client "hl2.exe" do
- fixed true
- end
- client instance: "phoenix", name: /^bsnes\ v\d+$/ do
- geometry [ 508, 195, 584, 510 ]
- fixed true
- end
- end
- #-----------------------------------------------------------------------------
- # Dynamic Views
- #-----------------------------------------------------------------------------
- view "gimp" do
- dynamic true
- client /^gimp-\d\.\d$/
- gravity :g15_l, instance: /^gimp-\d\.\d$/, role: "gimp-toolbox"
- gravity :g15_r, instance: /^gimp-\d\.\d$/, role: "gimp-image-window"
- end
- view "files" do
- dynamic true
- client "Thunar"
- end
- view "chrome" do
- dynamic true
- client class: "Google-chrome" do
- borderless true
- end
- gravity :chrome_l, instance: /^crx_[a-z]{32}$/, class: "Google-chrome"
- gravity :chrome_r, instance: "google-chrome"
- end
- #-----------------------------------------------------------------------------
- # Sublets
- #-----------------------------------------------------------------------------
- sublet :clock do
- interval 1
- format_string "%a %m.%d - %H:%M"
- end
- #-----------------------------------------------------------------------------
- # Events
- #-----------------------------------------------------------------------------
- on :client_create do |c|
- #puts "CREATE"
- c.focus
- #puts c.name
- #puts c.gravity
- #puts c.gravity.name
- #c.views.first.jump
- #client_gravity_grid c
- #puts "END CREATE"
- end
- #on :tile do |g|
- # puts "TILE"
- # puts g
- # #gravs = Subtlext::Gravity[:all].reject { |x| not x.tiling == :grid }
- # #puts gravs
- # puts "END TILE"
- #end
- on :client_create do |c|
- p Subtlext::View[:all]
- puts
- p Subtlext::View[3]
- p Subtlext::View[0]
- puts
- p Subtlext::View[3].prev.prev.prev.next
- p Subtlext::View[0].next
- end
- on :client_create do |c|
- p Subtlext::View[1] == Subtlext::View[0].next
- p Subtlext::View[0] == Subtlext::View[1].prev
- end
Advertisement
Add Comment
Please, Sign In to add comment