2013-12-19 06:22:49 +01:00
local setmetatable , type = setmetatable , type
local ipairs , pairs = ipairs , pairs
2014-03-28 07:13:12 +01:00
local button = require ( " awful.button " )
local beautiful = require ( " beautiful " )
local tag = require ( " awful.tag " )
local client2 = require ( " awful.client " )
local radical = require ( " radical " )
local util = require ( " awful.util " )
local wibox = require ( " wibox " )
local tag_list = require ( " radical.impl.taglist " )
2013-12-20 06:25:54 +01:00
local capi = { client = client , mouse = mouse , screen = screen }
2013-12-19 06:22:49 +01:00
local module , pause_monitoring = { } , false
2014-10-18 05:52:26 +02:00
-- Using viewonly to change tag will create an unwanted
-- focus event in the awful stack. While this module does
-- not use it, it try to be a good citizen and avoid corrupting
-- it.
local lock_history = false
local function awful_client_history_add ( c )
if not lock_history then
client2.focus . history.add ( c )
end
end
2013-12-19 06:22:49 +01:00
-- Keep its own history instead of using awful.client.focus.history
local focusIdx , focusTable = 1 , setmetatable ( { } , { __mode = ' v ' } )
2014-05-01 05:44:00 +02:00
local focusTag = setmetatable ( { } , { __mode = ' v ' } )
2013-12-19 06:22:49 +01:00
local function push_focus ( c )
2013-12-31 05:53:07 +01:00
if c and not pause_monitoring then
2013-12-19 06:22:49 +01:00
focusTable [ c ] = focusIdx
focusIdx = focusIdx + 1
2014-05-01 05:44:00 +02:00
focusTag [ c ] = tag.selected ( c.screen )
2013-12-19 06:22:49 +01:00
end
end
capi.client . connect_signal ( " focus " , push_focus )
-- Remove client when closed
client.connect_signal ( " unmanage " , function ( c )
focusTable [ c ] = nil
end )
local function compare ( a , b )
return a [ 1 ] > b [ 1 ]
end
local function get_history ( screen )
local result = { }
for k , v in pairs ( focusTable ) do
result [ # result + 1 ] = { v , k }
end
local orphanCount = - 100
for k , v in ipairs ( capi.client . get ( screen or 1 ) ) do
if not focusTable [ v ] then
result [ # result + 1 ] = setmetatable ( { orphanCount , v } , { __mode = ' v ' } )
orphanCount = orphanCount - 1
end
end
table.sort ( result , compare )
return result
end
-- Simulate a titlebar
local function button_group ( args )
local widget = wibox.widget . imagebox ( )
2013-12-20 06:25:54 +01:00
widget : set_image ( module.titlebar_path .. args.field .. " _normal_ " .. ( args.checked ( ) and " active " or " inactive " ) .. " .png " )
2013-12-19 06:22:49 +01:00
widget : buttons ( util.table . join ( button ( { } , 1 , args.onclick ) ) )
return widget
end
local function select_next ( menu )
local item = menu.next_item
2014-08-10 05:45:03 +02:00
if not item then return end
2013-12-19 06:22:49 +01:00
item.selected = true
2014-05-01 05:44:00 +02:00
item.button1 ( nil , nil , nil , nil , true )
2013-12-19 06:22:49 +01:00
return true
end
2013-12-20 06:25:54 +01:00
local function is_in_tag ( t , c )
for k , v in ipairs ( c : tags ( ) ) do if t == v then return true end end
return false
end
2016-02-28 08:04:51 +01:00
local function reload_infoshapes ( client , item )
local infoshapes = { }
2014-03-28 07:13:12 +01:00
for k , v in ipairs ( client : tags ( ) ) do
2016-02-28 08:04:51 +01:00
infoshapes [ # infoshapes + 1 ] = { text = v.name }
2014-03-28 07:13:12 +01:00
end
if item then
2016-02-28 08:04:51 +01:00
item.infoshapes = infoshapes
2014-03-28 07:13:12 +01:00
end
2016-02-28 08:04:51 +01:00
return infoshapes
2014-03-28 07:13:12 +01:00
end
local function reload_highlight ( i )
if i.selected then
local hl = { }
for k , v in ipairs ( i.client : tags ( ) ) do
hl [ # hl + 1 ] = v
end
tag_list.highlight ( hl )
2014-08-08 08:00:49 +02:00
2014-10-18 05:52:26 +02:00
i._internal . border_color_back = i._internal . border_color_back or i.client . border_color
2014-08-08 08:00:49 +02:00
i.client . border_color = beautiful.bg_urgent
elseif i._internal . border_color_back then
i.client . border_color = i._internal . border_color_back
2014-03-28 07:13:12 +01:00
end
end
2013-12-20 06:25:54 +01:00
local function new ( args )
2014-03-02 22:29:07 +01:00
local histo = get_history ( --[[screen]] )
2014-08-10 05:45:03 +02:00
if # histo == 0 then
2014-03-02 22:29:07 +01:00
return
end
2014-03-22 22:35:43 +01:00
2015-03-08 23:37:32 +01:00
local scr = capi.client . focus and capi.client . focus.screen or capi.mouse . screen
local t , auto_release = tag.selected ( scr ) , args.auto_release
2014-05-01 05:44:00 +02:00
local currentMenu = radical.box ( { filter = true , show_filter = not auto_release , autodiscard = true ,
2015-03-08 23:37:32 +01:00
disable_markup = true , fkeys_prefix = not auto_release , width = ( ( ( capi.screen [ scr ] ) . geometry.width ) / 2 ) ,
2014-08-08 08:00:49 +02:00
icon_transformation = beautiful.alttab_icon_transformation , filter_underlay = " Use [Shift] and [Control] to toggle clients " , filter_underlay_color = beautiful.menu_bg_normal ,
2014-03-22 22:35:43 +01:00
filter_placeholder = " <span fgcolor=' " .. ( beautiful.menu_fg_disabled or beautiful.fg_disabled or " #777777 " ) .. " '>Type to filter</span> " } )
2014-10-11 09:10:55 +02:00
currentMenu.margins . top = currentMenu.border_width
currentMenu.margins . bottom = currentMenu.border_width
2014-05-01 05:44:00 +02:00
if not auto_release then
local pref_bg = wibox.widget . background ( )
local pref_l = wibox.layout . align.horizontal ( )
2015-12-29 11:19:23 +01:00
pref_bg.fit = function ( s , c , w , h )
local w2 , h2 = wibox.widget . background.fit ( s , c , w , h )
2014-05-01 05:44:00 +02:00
return w2 , currentMenu.item_height
end
pref_bg : set_bg ( currentMenu.bg_alternate )
local tb2 = wibox.widget . textbox ( )
tb2 : set_text ( " foo!!!! " )
pref_l : set_first ( tb2 )
pref_bg : set_widget ( pref_l )
local pref_menu , pref_menu_l = radical.bar { item_style = radical.item . style.basic }
2015-12-29 11:19:23 +01:00
-- pref_menu:add_widget(radical.widgets.separator(pref_menu,radical.widgets.separator.VERTICAL))
2014-05-01 05:44:00 +02:00
pref_menu : add_item { text = " Exclusive " }
2015-12-29 11:19:23 +01:00
-- pref_menu:add_widget(radical.widgets.separator(pref_menu,radical.widgets.separator.VERTICAL))
2014-05-01 05:44:00 +02:00
pref_menu : add_item { text = " 12 clients " }
2015-12-29 11:19:23 +01:00
-- pref_menu:add_widget(radical.widgets.separator(pref_menu,radical.widgets.separator.VERTICAL))
2014-05-01 05:44:00 +02:00
pref_menu : add_item { text = " All Screens " }
2015-12-29 11:19:23 +01:00
-- pref_menu:add_widget(radical.widgets.separator(pref_menu,radical.widgets.separator.VERTICAL))
2014-05-01 05:44:00 +02:00
pref_l : set_third ( pref_menu_l )
currentMenu : add_prefix_widget ( pref_bg )
2014-03-22 22:35:43 +01:00
end
2013-12-19 06:22:49 +01:00
currentMenu : add_key_hook ( { } , " Tab " , " press " , select_next )
2013-12-20 06:25:54 +01:00
currentMenu : add_key_hook ( { } , " Shift_L " , " press " , function ( )
2014-10-18 05:52:26 +02:00
local item = currentMenu._current_item
item.checked = not item.checked
local c = item.client
2015-03-08 23:37:32 +01:00
if c.screen ~= scr then return end
2014-10-18 05:52:26 +02:00
client2.toggletag ( t , c )
2016-02-28 08:04:51 +01:00
reload_infoshapes ( c , item )
2014-05-01 05:44:00 +02:00
if not auto_release then
2014-10-18 05:52:26 +02:00
reload_highlight ( item )
end
if item._internal . border_color_back then
c.border_color = item._internal . border_color_back
2014-05-01 05:44:00 +02:00
end
2013-12-20 06:25:54 +01:00
return true
end )
2014-08-08 08:00:49 +02:00
currentMenu : add_key_hook ( { } , " Control_L " , " press " , function ( )
2014-10-18 05:52:26 +02:00
local item = currentMenu._current_item
item.checked = not item.checked
2015-03-08 23:37:32 +01:00
local c = item.client
if c.screen ~= scr then return end
client2.movetotag ( t , c )
2016-02-28 08:04:51 +01:00
reload_infoshapes ( c , item )
2014-08-08 08:00:49 +02:00
if not auto_release then
2014-10-18 05:52:26 +02:00
reload_highlight ( item )
2014-08-08 08:00:49 +02:00
end
return true
end )
2013-12-19 06:22:49 +01:00
2014-08-10 05:45:03 +02:00
for k , v2 in ipairs ( histo ) do
local l , v = wibox.layout . fixed.horizontal ( ) , v2 [ 2 ]
if not auto_release and module.titlebar_path then
l : add ( button_group ( { client = v , field = " floating " , focus = false , checked = function ( ) return v.floating end , onclick = function ( ) v.floating = not v.floating end } ) )
l : add ( button_group ( { client = v , field = " maximized " , focus = false , checked = function ( ) return v.maximized end , onclick = function ( ) v.maximized = not v.maximized end } ) )
l : add ( button_group ( { client = v , field = " sticky " , focus = false , checked = function ( ) return v.sticky end , onclick = function ( ) v.sticky = not v.sticky end } ) )
l : add ( button_group ( { client = v , field = " ontop " , focus = false , checked = function ( ) return v.ontop end , onclick = function ( ) v.ontop = not v.ontop end } ) )
2016-02-28 08:04:51 +01:00
l : add ( button_group ( { client = v , field = " close " , focus = false , checked = function ( ) return false end , onclick = function ( ) v : kill ( ) ; currentMenu.visible = false ; end } ) )
2015-12-29 11:19:23 +01:00
l.fit = function ( s , c , w , h ) return 5 * h , h end
2014-08-10 05:45:03 +02:00
end
2013-12-19 06:22:49 +01:00
2016-02-28 08:04:51 +01:00
local underlays = reload_infoshapes ( v )
2014-08-10 05:45:03 +02:00
local i = currentMenu : add_item ( {
text = v.name ,
icon = v.icon or module.default_icon ,
suffix_widget = not auto_release and l or nil ,
selected = capi.client . focus and capi.client . focus == v ,
2016-02-28 08:04:51 +01:00
infoshapes = underlays ,
2015-03-08 23:37:32 +01:00
checkable = ( not auto_release ) and v.screen == scr ,
checked = v.screen == scr and ( not auto_release and is_in_tag ( t , v ) ) or nil ,
2014-08-10 05:45:03 +02:00
button1 = function ( a , b , c , d , no_hide )
local t = focusTag [ v ] or v : tags ( ) [ 1 ]
if t and t.selected == false and not util.table . hasitem ( v : tags ( ) , tag.selected ( v.screen ) ) then
2014-10-18 05:52:26 +02:00
lock_history = true
2014-08-10 05:45:03 +02:00
tag.viewonly ( t )
2014-10-18 05:52:26 +02:00
lock_history = false
2014-08-10 05:45:03 +02:00
end
capi.client . focus = v
v : raise ( )
if not no_hide then
currentMenu.visible = false
end
end ,
} )
i.client = v
2014-01-18 08:20:07 +01:00
2014-08-10 05:45:03 +02:00
if not auto_release then
i : connect_signal ( " selected::changed " , reload_highlight )
2013-12-19 06:22:49 +01:00
end
end
2013-12-31 05:53:07 +01:00
if auto_release then
2013-12-20 06:25:54 +01:00
currentMenu : add_key_hook ( { } , " Alt_L " , " release " , function ( _ )
currentMenu.visible = false
return false
end )
2013-12-19 06:22:49 +01:00
select_next ( currentMenu )
end
2013-12-20 06:25:54 +01:00
pause_monitoring , currentMenu.visible = true , true
2013-12-19 06:22:49 +01:00
currentMenu : connect_signal ( " visible::changed " , function ( m )
2014-03-28 07:13:12 +01:00
if not m.visible then
pause_monitoring = false
push_focus ( capi.client . focus )
2014-05-01 05:44:00 +02:00
if not auto_release then
tag_list.highlight ( )
end
2014-08-08 08:00:49 +02:00
if currentMenu._current_item and currentMenu._current_item . _internal.border_color_back then
currentMenu._current_item . client.border_color = currentMenu._current_item . _internal.border_color_back
end
2014-03-28 07:13:12 +01:00
end
2013-12-19 06:22:49 +01:00
end )
return currentMenu
end
function module . altTab ( args )
2013-12-20 06:25:54 +01:00
new ( { leap = 1 , auto_release = ( args or { } ) . auto_release } )
2013-12-19 06:22:49 +01:00
end
function module . altTabBack ( args )
2013-12-20 06:25:54 +01:00
new ( { leap = - 1 , auto_release = ( args or { } ) . auto_release } )
2013-12-19 06:22:49 +01:00
end
2014-10-18 05:52:26 +02:00
-- Sometime need to lock .add
capi.client . disconnect_signal ( " focus " , client2.focus . history.add )
capi.client . connect_signal ( " focus " , awful_client_history_add )
2013-12-19 06:22:49 +01:00
return setmetatable ( module , { __call = function ( _ , ... ) return new ( ... ) end } )
-- kate: space-indent on; indent-width 2; replace-tabs on;