radical/impl/tasklist/init.lua

314 lines
9.6 KiB
Lua
Raw Normal View History

2014-02-08 06:52:42 +01:00
---------------------------------------------------------------------------
-- @author Emmanuel Lepage Vallee <elv1313@gmail.com>
-- @copyright 2014 Emmanuel Lepage Vallee
-- @release devel
-- @note Based on the original tasklist.lua
-- @license GPLv2+ because of copy paste from the old tasklist.lua
---------------------------------------------------------------------------
2014-03-20 04:13:55 +01:00
local capi = {client = client,tag=tag}
2014-02-15 05:35:53 +01:00
local rawset = rawset
local radical = require( "radical" )
local tag = require( "awful.tag" )
local beautiful = require( "beautiful" )
local client = require( "awful.client" )
local wibox = require( "wibox" )
local surface = require( "gears.surface")
local client_menu = require( "radical.impl.tasklist.client_menu")
local theme = require( "radical.theme")
local rad_client = require( "radical.impl.common.client")
2014-02-08 06:52:42 +01:00
local sticky,urgent,instances,module = {extensions=require("radical.impl.tasklist.extensions")},{},{},{}
local _cache = setmetatable({}, { __mode = 'k' })
local MINIMIZED = 101
theme.register_color(MINIMIZED , "minimized" , "tasklist_minimized" , true )
2014-02-08 06:52:42 +01:00
-- Default button implementation
module.buttons = {
[1] = function (c)
if c == capi.client.focus then
c.minimized = true
else
-- Without this, the following
-- :isvisible() makes no sense
c.minimized = false
if not c:isvisible() then
tag.viewonly(c:tags()[1])
end
-- This will also un-minimize
-- the client, if needed
capi.client.focus = c
c:raise()
end
end,
[3] = function(c)
client_menu.client = c
local menu = client_menu()
menu.visible = not menu.visible
end,
[4] = function ()
client.focus.byidx(1)
2014-04-19 05:33:13 +02:00
if capi.client.focus then capi.client.focus:raise() end
end,
[5] = function ()
client.focus.byidx(-1)
2014-04-19 05:33:13 +02:00
if capi.client.focus then capi.client.focus:raise() end
end
}
local function display_screenshot(c,geo,visible)
if not visible and prev_menu then
prev_menu.visible = false
return
end
if not c then return end
return rad_client.screenshot(c,geo)
end
2014-02-08 06:52:42 +01:00
local function sticky_callback(c)
local val = c.sticky
sticky[c] = val and true or nil
2014-03-26 05:21:42 +01:00
local menu = instances[c.screen].menu
2014-03-20 04:13:55 +01:00
local is_in_tag = false
for _,t in ipairs(tag.selectedlist(k)) do
for k2,v2 in ipairs(c:tags()) do
if v2 == t then
is_in_tag = true
break
end
end
if is_in_tag then break end
end
if not is_in_tag then
2014-02-08 06:52:42 +01:00
if val then
2014-03-20 04:13:55 +01:00
menu:append(_cache[c])
2014-02-08 06:52:42 +01:00
else
2014-03-20 04:13:55 +01:00
menu:remove(_cache[c])
2014-02-08 06:52:42 +01:00
end
end
end
local function urgent_callback(c)
local val = c.urgent
urgent[c] = val and true or nil
2014-03-20 04:13:55 +01:00
local item = _cache[c]
2014-02-23 05:59:03 +01:00
if item then
item.state[radical.base.item_flags.URGENT] = val or nil
end
2014-02-08 06:52:42 +01:00
end
local function minimize_callback(c)
2014-03-20 04:13:55 +01:00
local item = _cache[c]
if item then
local val = c.minimized
item.state[MINIMIZED] = val or nil
end
end
2014-02-08 06:52:42 +01:00
local function unmanage_callback(c)
sticky[c] = nil
urgent[c] = nil
for k,v in ipairs(instances) do
2014-03-20 04:13:55 +01:00
v.menu:remove(_cache[c])
2014-02-08 06:52:42 +01:00
end
2014-03-20 04:13:55 +01:00
_cache[c] = nil
2014-02-08 06:52:42 +01:00
end
2014-02-08 07:31:45 +01:00
-- Reload <float> <ontop> and <sticky> labels
local function reload_underlay(c)
2014-03-20 04:13:55 +01:00
local udl,item = {},_cache[c]
2014-02-08 07:31:45 +01:00
if item then
if c.ontop then
udl[#udl+1] = "ontop"
end
if client.floating.get(c) then
udl[#udl+1] = "float"
end
if c.sticky then
udl[#udl+1] = "sticky"
2014-02-08 06:52:42 +01:00
end
2014-02-08 07:31:45 +01:00
item.underlay = udl
item.widget:emit_signal("widget::updated")
end
end
2014-02-08 06:52:42 +01:00
-- Reload title and icon
local function reload_content(c,b,a)
2014-03-20 04:13:55 +01:00
local item = _cache[c]
if item then
2014-12-24 06:53:09 +01:00
-- if not beautiful.tasklist_disable_icon then
-- item.icon = surface(c.icon) or beautiful.tasklist_default_icon
-- end
2014-03-02 22:29:07 +01:00
item.text = c.name or "N/A"
end
end
2014-03-20 04:13:55 +01:00
2014-02-08 07:31:45 +01:00
local function create_client_item(c,screen)
2014-03-20 04:13:55 +01:00
local item = _cache[c]
2014-02-08 07:31:45 +01:00
local menu = instances[screen].menu
-- If it already exist, don't waste time creating a copy
2014-03-20 04:13:55 +01:00
if item then
menu:append(item)
return item
2014-02-08 06:52:42 +01:00
end
2014-02-08 07:31:45 +01:00
-- Too bad, let's create a new one
local suf_w = wibox.layout.fixed.horizontal()
2014-11-15 05:46:06 +01:00
item = menu:add_item{text=c.name,icon=(not beautiful.tasklist_disable_icon) and surface(c.icon),suffix_widget=suf_w}
item.add_suffix = function(w,w2)
suf_w:add(w2)
end
item.client = c
2014-03-20 04:13:55 +01:00
_cache[c] = item
return item
2014-02-08 07:31:45 +01:00
end
2014-03-20 04:13:55 +01:00
-- Add client to the tasklist
2014-02-08 07:31:45 +01:00
local function add_client(c,screen)
if not (c.skip_taskbar or c.hidden or c.type == "splash" or c.type == "dock" or c.type == "desktop") and c.screen == screen then
local ret = create_client_item(c,screen)
reload_underlay(c)
2014-03-20 04:13:55 +01:00
if capi.client.focus == c then
2014-02-08 07:31:45 +01:00
ret.selected = true
2014-02-08 06:52:42 +01:00
end
end
2014-02-08 07:31:45 +01:00
end
2014-03-20 04:13:55 +01:00
-- Clear the menu and repopulate it
local function load_clients(t)
local screen = tag.getscreen(t)
2014-03-26 05:21:42 +01:00
if not t or not screen or not instances[screen] then return end
2014-03-20 04:13:55 +01:00
local menu = instances[screen].menu
local clients = {}
local selected = tag.selectedlist(screen)
-- The "#selected > 0" is for reseting when multiple tags are selected
if t.selected or #selected > 0 then
2014-03-20 04:13:55 +01:00
menu:clear()
for k2,t2 in ipairs(selected) do
for k, c in ipairs(t2:clients()) do
if not c.sticky then
add_client(c,screen)
clients[#clients+1] = c
end
2014-03-20 04:13:55 +01:00
end
end
for c,_ in pairs(sticky) do
add_client(c,screen)
end
end
end
-- Reload the tag
local function tag_screen_changed(t)
if not t.selected then return end
local screen = tag.getscreen(t)
load_clients(t)
end
2014-02-08 07:31:45 +01:00
-- Unselect the old focussed client
local function unfocus(c)
2014-03-20 04:13:55 +01:00
local item = _cache[c]
2014-02-08 07:31:45 +01:00
if item and item.selected then
item.selected = false
end
end
-- Select the newly focussed client
local function focus(c)
2014-03-20 04:13:55 +01:00
local item = _cache[c]
2014-02-08 07:31:45 +01:00
if item then
item.selected = true
end
end
2014-03-26 05:21:42 +01:00
-- Remove the client from the tag
local function untagged(c,t)
local item = _cache[c]
2014-03-26 21:18:59 +01:00
local screen = tag.getscreen(t)
if not item or not instances[screen] then return end
local menu = instances[screen].menu
2014-03-26 05:21:42 +01:00
if t.selected then
menu:remove(item)
end
end
-- Add and remove clients from the tasklist
local function tagged(c,t)
if t.selected and not c.sticky then
add_client(c,tag.getscreen(t))
end
end
2014-02-08 07:31:45 +01:00
local function new(screen)
local args = {
select_on = radical.base.event.NEVER ,
disable_markup = true ,
fg = beautiful.tasklist_fg or beautiful.fg_normal ,
bg = beautiful.tasklist_bg or beautiful.bg_normal ,
underlay_style = beautiful.tasklist_underlay_style or radical.widgets.underlay.draw_arrow,
icon_transformation = beautiful.tasklist_icon_transformation ,
default_item_margins = beautiful.tasklist_default_item_margins ,
default_margins = beautiful.tasklist_default_margins ,
item_style = beautiful.tasklist_item_style ,
style = beautiful.tasklist_style ,
2014-11-15 05:46:06 +01:00
spacing = beautiful.tasklist_spacing ,
2014-12-24 06:53:09 +01:00
icon_per_state = true ,
2014-02-09 06:54:59 +01:00
}
for k,v in ipairs {"hover","urgent","minimized","focus"} do
args["bg_"..v] = beautiful["tasklist_bg_"..v]
args["fg_"..v] = beautiful["tasklist_fg_"..v]
args["underlay_bg_"..v] = beautiful["tasklist_underlay_bg_"..v]
end
local menu = radical.flexbar(args)
-- overlay = function(data,item,cd,w,h)
-- print("foo!")
-- end,
-- }
2014-02-08 06:52:42 +01:00
-- Connect to a bunch of signals
instances[screen] = {menu = menu}
2014-02-08 06:52:42 +01:00
load_clients(tag.selected(screen))
menu:connect_signal("button::press",function(menu,item,button_id,mod)
if module.buttons and module.buttons[button_id] then
module.buttons[button_id](item.client,menu,item,button_id,mod)
end
end)
2014-02-15 05:35:53 +01:00
menu:connect_signal("long::hover",function(m,i,mod,geo)
display_screenshot(i.client,geo,true)
end)
2014-02-15 05:35:53 +01:00
return menu,menu._internal.layout
2014-02-08 06:52:42 +01:00
end
function module.item(client)
return _cache[client]
end
2014-02-08 06:52:42 +01:00
-- Global callbacks
capi.client.connect_signal("property::sticky" , sticky_callback )
capi.client.connect_signal("property::urgent" , urgent_callback )
capi.client.connect_signal("unmanage" , unmanage_callback )
capi.client.connect_signal("focus" , focus )
capi.client.connect_signal("unfocus" , unfocus )
capi.client.connect_signal("property::sticky" , reload_underlay )
capi.client.connect_signal("property::ontop" , reload_underlay )
capi.client.connect_signal("property::floating" , reload_underlay )
capi.client.connect_signal("property::name" , reload_content )
capi.client.connect_signal("property::icon" , reload_content )
capi.client.connect_signal("property::minimized", minimize_callback )
capi.client.connect_signal("tagged" , tagged )
capi.client.connect_signal("untagged" , untagged )
capi.tag.connect_signal ("property::screen" , tag_screen_changed )
capi.tag.connect_signal ("property::selected" , load_clients )
capi.tag.connect_signal ("property::activated", load_clients )
2014-02-08 06:52:42 +01:00
return setmetatable(module, { __call = function(_, ...) return new(...) end })
-- kate: space-indent on; indent-width 2; replace-tabs on;