--------------------------------------------------------------------------- -- @author Julien Danjou <julien@danjou.info> -- @copyright 2008 Julien Danjou -- @release @AWESOME_VERSION@ --------------------------------------------------------------------------- -- Grab environment we need local math = math local image = image local pairs = pairs local otable = otable local capi = { wibox = wibox, widget = widget, button = button, client = client, } local beautiful = require("beautiful") local hooks = require("awful.hooks") local util = require("awful.util") local widget = require("awful.widget") local mouse = require("awful.mouse") --- Titlebar module for awful module("awful.titlebar") -- Privata data local data = otable() --- Create a standard titlebar. -- @param c The client. -- @param args Arguments. -- modkey: the modkey used for the bindings. -- fg: the foreground color. -- bg: the background color. -- fg_focus: the foreground color for focused window. -- fg_focus: the background color for focused window. -- width: the titlebar width function add(c, args) if not c or (c.type ~= "normal" and c.type ~= "dialog") then return end if not args then args = {} end local theme = beautiful.get() -- Store colors data[c] = {} data[c].fg = args.fg or theme.titlebar_fg_normal or theme.fg_normal data[c].bg = args.bg or theme.titlebar_bg_normal or theme.bg_normal data[c].fg_focus = args.fg_focus or theme.titlebar_fg_focus or theme.fg_focus data[c].bg_focus = args.bg_focus or theme.titlebar_bg_focus or theme.bg_focus data[c].width = args.width local tb = capi.wibox(args) local title = capi.widget({ type = "textbox", align = "flex" }) if c.name then title.text = " " .. util.escape(c.name) .. " " else title.text = nil end -- Redirect relevant events to the client the titlebar belongs to local bts = { capi.button({ }, 1, function (t) capi.client.focus = t.client t.client:raise() mouse.client.move(t.client) end), capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end), capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end) } title:buttons(bts) function title.mouse_enter(s) hooks.user.call('mouse_enter', c) end local appicon = capi.widget({ type = "imagebox", align = "left" }) appicon.image = c.icon -- Also redirect events for appicon (So the entire titlebar behaves consistently) appicon:buttons(bts) function appicon.mouse_enter(s) hooks.user.call('mouse_enter', c) end local closef if theme.titlebar_close_button_focus then closef = widget.button({ align = "right", image = image(theme.titlebar_close_button_focus) }) end local close if theme.titlebar_close_button_normal then close = widget.button({ align = "right", image = image(theme.titlebar_close_button_normal) }) end if close or closef then -- Bind kill button, also allow moving and resizing on this widget local bts = { capi.button({ }, 1, nil, function (t) t.client:kill() end), capi.button({ args.modkey }, 1, function (t) mouse.client.move(t.client) end), capi.button({ args.modkey }, 3, function (t) mouse.client.resize(t.client) end) } if close then local rbts = close:buttons() for k, v in pairs(rbts) do bts[#bts + 1] = v end close:buttons(bts) function close.mouse_enter(s) hooks.user.call('mouse_enter', c) end end if closef then local rbts = closef:buttons() for k, v in pairs(rbts) do bts[#bts + 1] = v end closef:buttons(bts) -- Needed for sloppy focus beheaviour function closef.mouse_enter(s) hooks.user.call('mouse_enter', c) end end end tb.widgets = { appicon = appicon, title = title, closef = closef, close = close } -- Store old geometry (including borders) local old_geom = c:geometry() c.titlebar = tb -- Resize the client so the same amount of space is occupied as before. -- But not when it's a dialog, because applications remember this new size. -- And everytime you open the dialog it shrinks further. if c.type ~= "dialog" then c:geometry(old_geom) end update(c) update(c, "geometry") end --- Update a titlebar. This should be called in some hooks. -- @param c The client to update. -- @param prop The property name which has changed. function update(c, prop) if c.titlebar and data[c] then local widgets = c.titlebar.widgets if prop == "name" then if widgets.title then widgets.title.text = " " .. util.escape(c.name) .. " " end elseif prop == "icon" then if widgets.appicon then widgets.appicon.image = c.icon end elseif prop == "geometry" then if data[c].width then if c.titlebar.position == "top" or c.titlebar.position == "bottom" then local w = math.min(data[c].width, c:geometry().width) c.titlebar:geometry({ width = w }) else local w = math.min(data[c].width, c:geometry().height) c.titlebar:geometry({ height = w }) end end end if capi.client.focus == c then c.titlebar.fg = data[c].fg_focus c.titlebar.bg = data[c].bg_focus if widgets.closef then widgets.closef.visible = true end if widgets.close then widgets.close.visible = false end else c.titlebar.fg = data[c].fg c.titlebar.bg = data[c].bg if widgets.closef then widgets.closef.visible = false end if widgets.close then widgets.close.visible = true end end end end --- Remove a titlebar from a client. -- @param c The client. function remove(c) local old_geom = c:geometry() c.titlebar = nil data[c] = nil -- Resize the client so the same amount of space is occupied as before. c:geometry(old_geom) end -- Register standards hooks hooks.focus.register(update) hooks.unfocus.register(update) hooks.property.register(update) hooks.unmanage.register(remove) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80