diff --git a/README.md b/README.md index 79c0cba..673ffb6 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,30 @@ The new client will have these properties set: See the [API documentation](https://jcrd.github.io/awesome-launch/) for descriptions of all functions. +## Widget + +A `launchbar` widget is provided to visualize pending clients. + +Customize the launchbar: +```lua +launch.widget.color = beautiful.fg_focus +``` + +Create a new launchbar for the given screen: +```lua +screen.connect_signal("request::desktop_decoration", function (s) + ... + s.launchbar = launch.widget.launchbar { + screen = s, + } + s.mywibox:setup { + ... + s.launchbar, + ... + } +end) +``` + ## License awesome-launch is licensed under the GNU General Public License v3.0 or later diff --git a/init.lua b/init.lua index 270d197..093160d 100644 --- a/init.lua +++ b/init.lua @@ -6,11 +6,112 @@ local awful = require("awful") local gears = require("gears") +local wibox = require("wibox") +local beautiful = require("beautiful") local uuid = require("uuid") uuid.seed() local pending = {} +local widgets = {} + +local launch = {} +launch.widget = {} + +launch.widget.color = beautiful.bg_focus +launch.widget.border_color = beautiful.fg_normal +launch.widget.width = beautiful.wibar_height or 20 +launch.widget.margins = 2 + +local function props_visible(s, p) + if p.screen and p.screen ~= s then + return false + end + local function selected(t) + if gears.table.hasitem(s.selected_tags, t) then + return true + end + end + if p.first_tag then + return selected(p.first_tag) + end + if p.tag then + return selected(p.tag) + end + if p.tags then + for _, t in ipairs(p.tags) do + if selected(t) then return true end + end + end +end + +local function update_widget(w) + w.widget:reset() + for _, data in pairs(pending) do + local visible = true + if w.only_tagged then + visible = props_visible(w.screen or awful.screen.focused(), + data.props) + end + if visible and (not w.filter or w.filter(data)) then + w.widget:add(data.widget) + end + end +end + +local function update_widgets() + for _, w in ipairs(widgets) do + update_widget(w) + end +end + +--- Create a new launchbar widget. +-- +-- The following options are available to customize the widget's +-- radialprogressbar: +-- +-- launch.widget.color +-- +-- launch.widget.border_color +-- +-- launch.widget.width +-- +-- launch.widget.margins +-- +-- @param args Table containing widget options +-- @param args.screen The screen pending clients must belong to. +-- @param args.filter Function to filter clients that are considered. +-- @param args.only_tagged Show only pending clients with selected tags. +-- @return The widget. +-- @function widget.launchbar +function launch.widget.launchbar(args) + args = args or {} + local w = { + screen = args.screen, + filter = args.filter, + only_tagged = true, + widget = wibox.widget { + layout = wibox.layout.fixed.horizontal, + }, + } + + if args.only_tagged == false then + w.only_tagged = false + end + + if w.only_tagged and w.screen then + screen.connect_signal("tag::history::update", function (s) + if s == w.screen then + update_widget(w) + end + end) + end + + table.insert(widgets, w) + + return w.widget +end + awesome.register_xproperty("WM_LAUNCH_ID", "string") @@ -31,11 +132,11 @@ awful.rules.add_rule_source("launch", end pending[id] = nil + update_widgets() end) awful.client.property.persist("cmdline", "string") -local launch = {} launch.client = {} local function get_ids() @@ -94,6 +195,7 @@ local function spawn(cmd, args) props = args.props or {}, pwd = args.pwd, callback = args.callback, + timeout = math.ceil(args.timeout or 10), } gears.table.crush(data.props, { @@ -101,12 +203,51 @@ local function spawn(cmd, args) cmdline = cmd, }) + local step = 1/2 data.timer = gears.timer { - timeout = args.timeout or 10, - single_shot = true, - callback = function () pending[id] = nil end, + timeout = step, + callback = function () + data.timeout = data.timeout - step + if data.timeout == 0 then + pending[id] = nil + update_widgets() + return false + else + data.widget.id_const.id_margin.id_progress.value = data.timeout + end + return true + end, } + if #widgets > 0 then + data.widget = wibox.widget { + { + { + { + id = "id_progress", + min_value = 0, + max_value = data.timeout, + value = data.timeout, + color = launch.widget.color, + border_color = launch.widget.border_color, + widget = wibox.container.radialprogressbar, + }, + id = "id_margin", + margins = launch.widget.margins, + layout = wibox.container.margin, + }, + id = "id_const", + width = launch.widget.width, + layout = wibox.container.constraint, + }, + { + text = cmd, + widget = wibox.widget.textbox, + }, + layout = wibox.layout.fixed.horizontal, + } + end + local launch = "wm-launch" if args.factory then @@ -126,6 +267,7 @@ local function spawn(cmd, args) end pending[id] = data + update_widgets() data.timer:start() return id