From 22d656903563f75678f3634964731ccf93355dfd Mon Sep 17 00:00:00 2001 From: ache Date: Mon, 13 Mar 2017 23:17:19 +0100 Subject: Init commit --- lib/awful/titlebar.lua | 509 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 lib/awful/titlebar.lua (limited to 'lib/awful/titlebar.lua') diff --git a/lib/awful/titlebar.lua b/lib/awful/titlebar.lua new file mode 100644 index 0000000..c055349 --- /dev/null +++ b/lib/awful/titlebar.lua @@ -0,0 +1,509 @@ +--------------------------------------------------------------------------- +--- Titlebars for awful. +-- +-- @author Uli Schlachter +-- @copyright 2012 Uli Schlachter +-- @module awful.titlebar +--------------------------------------------------------------------------- + +local error = error +local type = type +local util = require("awful.util") +local abutton = require("awful.button") +local aclient = require("awful.client") +local atooltip = require("awful.tooltip") +local beautiful = require("beautiful") +local drawable = require("wibox.drawable") +local imagebox = require("wibox.widget.imagebox") +local textbox = require("wibox.widget.textbox") +local base = require("wibox.widget.base") +local capi = { + client = client +} +local titlebar = { + widget = {} +} + +--- The titlebar foreground (text) color. +-- @beautiful beautiful.titlebar_fg_normal +-- @param color +-- @see gears.color + +--- The titlebar background color. +-- @beautiful beautiful.titlebar_bg_normal +-- @param color +-- @see gears.color + +--- The titlebar background image image. +-- @beautiful beautiful.titlebar_bgimage_normal +-- @param surface +-- @see gears.surface + +--- The titlebar foreground (text) color. +-- @beautiful beautiful.titlebar_fg +-- @param color +-- @see gears.color + +--- The titlebar background color. +-- @beautiful beautiful.titlebar_bg +-- @param color +-- @see gears.color + +--- The titlebar background image image. +-- @beautiful beautiful.titlebar_bgimage +-- @param surface +-- @see gears.surface + +--- The focused titlebar foreground (text) color. +-- @beautiful beautiful.titlebar_fg_focus +-- @param color +-- @see gears.color + +--- The focused titlebar background color. +-- @beautiful beautiful.titlebar_bg_focus +-- @param color +-- @see gears.color + +--- The focused titlebar background image image. +-- @beautiful beautiful.titlebar_bgimage_focus +-- @param surface +-- @see gears.surface + +--- floating_button_normal. +-- @beautiful beautiful.titlebar_floating_button_normal +-- @param surface +-- @see gears.surface + +--- maximized_button_normal. +-- @beautiful beautiful.titlebar_maximized_button_normal +-- @param surface +-- @see gears.surface + +--- minimize_button_normal +-- @beautiful beautiful.titlebar_minimize_button_normal +-- @param surface +-- @see gears.surface + +--- close_button_normal. +-- @beautiful beautiful.titlebar_close_button_normal +-- @param surface +-- @see gears.surface + +--- ontop_button_normal. +-- @beautiful beautiful.titlebar_ontop_button_normal +-- @param surface +-- @see gears.surface + +--- sticky_button_normal. +-- @beautiful beautiful.titlebar_sticky_button_normal +-- @param surface +-- @see gears.surface + +--- floating_button_focus. +-- @beautiful beautiful.titlebar_floating_button_focus +-- @param surface +-- @see gears.surface + +--- maximized_button_focus. +-- @beautiful beautiful.titlebar_maximized_button_focus +-- @param surface +-- @see gears.surface + +--- minimize_button_focus. +-- @beautiful beautiful.titlebar_minimize_button_focus +-- @param surface +-- @see gears.surface + +--- close_button_focus. +-- @beautiful beautiful.titlebar_close_button_focus +-- @param surface +-- @see gears.surface + +--- ontop_button_focus. +-- @beautiful beautiful.titlebar_ontop_button_focus +-- @param surface +-- @see gears.surface + +--- sticky_button_focus. +-- @beautiful beautiful.titlebar_sticky_button_focus +-- @param surface +-- @see gears.surface + +--- floating_button_normal_active. +-- @beautiful beautiful.titlebar_floating_button_normal_active +-- @param surface +-- @see gears.surface + +--- maximized_button_normal_active. +-- @beautiful beautiful.titlebar_maximized_button_normal_active +-- @param surface +-- @see gears.surface + +--- ontop_button_normal_active. +-- @beautiful beautiful.titlebar_ontop_button_normal_active +-- @param surface +-- @see gears.surface + +--- sticky_button_normal_active. +-- @beautiful beautiful.titlebar_sticky_button_normal_active +-- @param surface +-- @see gears.surface + +--- floating_button_focus_active. +-- @beautiful beautiful.titlebar_floating_button_focus_active +-- @param surface +-- @see gears.surface + +--- maximized_button_focus_active. +-- @beautiful beautiful.titlebar_maximized_button_focus_active +-- @param surface +-- @see gears.surface + +--- ontop_button_focus_active. +-- @beautiful beautiful.titlebar_ontop_button_focus_active +-- @param surface +-- @see gears.surface + +--- sticky_button_focus_active. +-- @beautiful beautiful.titlebar_sticky_button_focus_active +-- @param surface +-- @see gears.surface + +--- floating_button_normal_inactive. +-- @beautiful beautiful.titlebar_floating_button_normal_inactive +-- @param surface +-- @see gears.surface + +--- maximized_button_normal_inactive. +-- @beautiful beautiful.titlebar_maximized_button_normal_inactive +-- @param surface +-- @see gears.surface + +--- ontop_button_normal_inactive. +-- @beautiful beautiful.titlebar_ontop_button_normal_inactive +-- @param surface +-- @see gears.surface + +--- sticky_button_normal_inactive. +-- @beautiful beautiful.titlebar_sticky_button_normal_inactive +-- @param surface +-- @see gears.surface + +--- floating_button_focus_inactive. +-- @beautiful beautiful.titlebar_floating_button_focus_inactive +-- @param surface +-- @see gears.surface + +--- maximized_button_focus_inactive. +-- @beautiful beautiful.titlebar_maximized_button_focus_inactive +-- @param surface +-- @see gears.surface + +--- ontop_button_focus_inactive. +-- @beautiful beautiful.titlebar_ontop_button_focus_inactive +-- @param surface +-- @see gears.surface + +--- sticky_button_focus_inactive. +-- @beautiful beautiful.titlebar_sticky_button_focus_inactive +-- @param surface +-- @see gears.surface + +--- Set a declarative widget hierarchy description. +-- See [The declarative layout system](../documentation/03-declarative-layout.md.html) +-- @param args An array containing the widgets disposition +-- @name setup +-- @class function + +--- Show tooltips when hover on titlebar buttons (defaults to 'true') +titlebar.enable_tooltip = true + +local all_titlebars = setmetatable({}, { __mode = 'k' }) + +-- Get a color for a titlebar, this tests many values from the array and the theme +local function get_color(name, c, args) + local suffix = "_normal" + if capi.client.focus == c then + suffix = "_focus" + end + local function get(array) + return array["titlebar_"..name..suffix] or array["titlebar_"..name] or array[name..suffix] or array[name] + end + return get(args) or get(beautiful) +end + +local function get_titlebar_function(c, position) + if position == "left" then + return c.titlebar_left + elseif position == "right" then + return c.titlebar_right + elseif position == "top" then + return c.titlebar_top + elseif position == "bottom" then + return c.titlebar_bottom + else + error("Invalid titlebar position '" .. position .. "'") + end +end + +--- Get a client's titlebar +-- @class function +-- @tparam client c The client for which a titlebar is wanted. +-- @tparam[opt={}] table args A table with extra arguments for the titlebar. +-- @tparam[opt=font.height*1.5] number args.size The height of the titlebar. +-- @tparam[opt=top] string args.position" values are `top`, +-- `left`, `right` and `bottom`. +-- @tparam[opt=top] string args.bg_normal +-- @tparam[opt=top] string args.bg_focus +-- @tparam[opt=top] string args.bgimage_normal +-- @tparam[opt=top] string args.bgimage_focus +-- @tparam[opt=top] string args.fg_normal +-- @tparam[opt=top] string args.fg_focus +-- @tparam[opt=top] string args.font +-- @name titlebar +local function new(c, args) + args = args or {} + local position = args.position or "top" + local size = args.size or util.round(beautiful.get_font_height(args.font) * 1.5) + local d = get_titlebar_function(c, position)(c, size) + + -- Make sure that there is never more than one titlebar for any given client + local bars = all_titlebars[c] + if not bars then + bars = {} + all_titlebars[c] = bars + end + + local ret + if not bars[position] then + local context = { + client = c, + position = position + } + ret = drawable(d, context, "awful.titlebar") + ret:_inform_visible(true) + local function update_colors() + local args_ = bars[position].args + ret:set_bg(get_color("bg", c, args_)) + ret:set_fg(get_color("fg", c, args_)) + ret:set_bgimage(get_color("bgimage", c, args_)) + end + + bars[position] = { + args = args, + drawable = ret, + update_colors = update_colors + } + + -- Update the colors when focus changes + c:connect_signal("focus", update_colors) + c:connect_signal("unfocus", update_colors) + + -- Inform the drawable when it becomes invisible + c:connect_signal("unmanage", function() ret:_inform_visible(false) end) + else + bars[position].args = args + ret = bars[position].drawable + end + + -- Make sure the titlebar has the right colors applied + bars[position].update_colors() + + -- Handle declarative/recursive widget container + ret.setup = base.widget.setup + + return ret +end + +--- Show a client's titlebar. +-- @param c The client whose titlebar is modified +-- @param[opt] position The position of the titlebar. Must be one of "left", +-- "right", "top", "bottom". Default is "top". +function titlebar.show(c, position) + position = position or "top" + local bars = all_titlebars[c] + local data = bars and bars[position] + local args = data and data.args + new(c, args) +end + +--- Hide a client's titlebar. +-- @param c The client whose titlebar is modified +-- @param[opt] position The position of the titlebar. Must be one of "left", +-- "right", "top", "bottom". Default is "top". +function titlebar.hide(c, position) + position = position or "top" + get_titlebar_function(c, position)(c, 0) +end + +--- Toggle a client's titlebar, hiding it if it is visible, otherwise showing it. +-- @param c The client whose titlebar is modified +-- @param[opt] position The position of the titlebar. Must be one of "left", +-- "right", "top", "bottom". Default is "top". +function titlebar.toggle(c, position) + position = position or "top" + local _, size = get_titlebar_function(c, position)(c) + if size == 0 then + titlebar.show(c, position) + else + titlebar.hide(c, position) + end +end + +--- Create a new titlewidget. A title widget displays the name of a client. +-- Please note that this returns a textbox and all of textbox' API is available. +-- This way, you can e.g. modify the font that is used. +-- @param c The client for which a titlewidget should be created. +-- @return The title widget. +function titlebar.widget.titlewidget(c) + local ret = textbox() + local function update() + ret:set_text(c.name or "") + end + c:connect_signal("property::name", update) + update() + + return ret +end + +--- Create a new icon widget. An icon widget displays the icon of a client. +-- Please note that this returns an imagebox and all of the imagebox' API is +-- available. This way, you can e.g. disallow resizes. +-- @param c The client for which an icon widget should be created. +-- @return The icon widget. +function titlebar.widget.iconwidget(c) + local ret = imagebox() + local function update() + ret:set_image(c.icon) + end + c:connect_signal("property::icon", update) + update() + + return ret +end + +--- Create a new button widget. A button widget displays an image and reacts to +-- mouse clicks. Please note that the caller has to make sure that this widget +-- gets redrawn when needed by calling the returned widget's update() function. +-- The selector function should return a value describing a state. If the value +-- is a boolean, either "active" or "inactive" are used. The actual image is +-- then found in the theme as "titlebar_[name]_button_[normal/focus]_[state]". +-- If that value does not exist, the focused state is ignored for the next try. +-- @param c The client for which a button is created. +-- @tparam string name Name of the button, used for accessing the theme and +-- in the tooltip. +-- @param selector A function that selects the image that should be displayed. +-- @param action Function that is called when the button is clicked. +-- @return The widget +function titlebar.widget.button(c, name, selector, action) + local ret = imagebox() + + if titlebar.enable_tooltip then + ret._private.tooltip = atooltip({ objects = {ret}, delay_show = 1 }) + ret._private.tooltip:set_text(name) + end + + local function update() + local img = selector(c) + if type(img) ~= "nil" then + -- Convert booleans automatically + if type(img) == "boolean" then + if img then + img = "active" + else + img = "inactive" + end + end + local prefix = "normal" + if capi.client.focus == c then + prefix = "focus" + end + if img ~= "" then + prefix = prefix .. "_" + end + -- First try with a prefix based on the client's focus state, + -- then try again without that prefix if nothing was found, + -- and finally, try a fallback for compatibility with Awesome 3.5 themes + local theme = beautiful["titlebar_" .. name .. "_button_" .. prefix .. img] + or beautiful["titlebar_" .. name .. "_button_" .. img] + or beautiful["titlebar_" .. name .. "_button_" .. prefix .. "_inactive"] + if theme then + img = theme + end + end + ret:set_image(img) + end + if action then + ret:buttons(abutton({ }, 1, nil, function() action(c, selector(c)) end)) + end + + ret.update = update + update() + + -- We do magic based on whether a client is focused above, so we need to + -- connect to the corresponding signal here. + c:connect_signal("focus", update) + c:connect_signal("unfocus", update) + + return ret +end + +--- Create a new float button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.floatingbutton(c) + local widget = titlebar.widget.button(c, "floating", aclient.object.get_floating, aclient.floating.toggle) + c:connect_signal("property::floating", widget.update) + return widget +end + +--- Create a new maximize button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.maximizedbutton(c) + local widget = titlebar.widget.button(c, "maximized", function(cl) + return cl.maximized_horizontal or cl.maximized_vertical + end, function(cl, state) + cl.maximized_horizontal = not state + cl.maximized_vertical = not state + end) + c:connect_signal("property::maximized_vertical", widget.update) + c:connect_signal("property::maximized_horizontal", widget.update) + return widget +end + +--- Create a new minimize button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.minimizebutton(c) + local widget = titlebar.widget.button(c, "minimize", function() return "" end, function(cl) cl.minimized = not cl.minimized end) + c:connect_signal("property::minimized", widget.update) + return widget +end + +--- Create a new closing button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.closebutton(c) + return titlebar.widget.button(c, "close", function() return "" end, function(cl) cl:kill() end) +end + +--- Create a new ontop button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.ontopbutton(c) + local widget = titlebar.widget.button(c, "ontop", function(cl) return cl.ontop end, function(cl, state) cl.ontop = not state end) + c:connect_signal("property::ontop", widget.update) + return widget +end + +--- Create a new sticky button for a client. +-- @param c The client for which the button is wanted. +function titlebar.widget.stickybutton(c) + local widget = titlebar.widget.button(c, "sticky", function(cl) return cl.sticky end, function(cl, state) cl.sticky = not state end) + c:connect_signal("property::sticky", widget.update) + return widget +end + +client.connect_signal("unmanage", function(c) + all_titlebars[c] = nil +end) + +return setmetatable(titlebar, { __call = function(_, ...) return new(...) end}) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- cgit v1.2.3-54-g00ecf