awful: split in several modules
Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
dfd380dde6
commit
34647e4e75
|
@ -22,10 +22,7 @@ include_directories(
|
|||
${AWESOME_REQUIRED_INCLUDE_DIRS}
|
||||
${AWESOME_OPTIONAL_INCLUDE_DIRS})
|
||||
|
||||
set(AWE_LUA_FILES
|
||||
${BUILD_DIR}/lib/tabulous.lua
|
||||
${BUILD_DIR}/lib/beautiful.lua
|
||||
${BUILD_DIR}/lib/awful.lua)
|
||||
file(GLOB_RECURSE AWE_LUA_FILES ${BUILD_DIR}/lib/*.lua)
|
||||
|
||||
set(AWE_CONF_FILE_DEFAULT ${BUILD_DIR}/awesomerc.lua)
|
||||
set(AWE_CONF_FILE rc.lua)
|
||||
|
@ -294,9 +291,10 @@ if(GENERATE_LUADOC)
|
|||
VERBATIM)
|
||||
# }}}
|
||||
|
||||
# dont include full path names in documentation
|
||||
foreach(filename ${AWE_LUA_FILES} ${capi_lua})
|
||||
get_filename_component(filename ${filename} NAME)
|
||||
# Generate documentation of lib//0lua
|
||||
file(GLOB_RECURSE lua_lib_files ${BUILD_DIR}/lib/*.lua)
|
||||
foreach(filename ${lua_lib_files})
|
||||
file(RELATIVE_PATH filename ${BUILD_DIR}/lib ${filename})
|
||||
set(luadoc_srcs ${luadoc_srcs} ${filename})
|
||||
endforeach()
|
||||
|
||||
|
@ -318,7 +316,7 @@ endif()
|
|||
# {{{ Installation
|
||||
install(TARGETS ${PROJECT_AWE_NAME} ${PROJECT_AWECLIENT_NAME} RUNTIME DESTINATION bin)
|
||||
install(FILES "utils/awsetbg" DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
|
||||
install(FILES ${AWE_LUA_FILES} DESTINATION ${AWESOME_LUA_LIB_PATH})
|
||||
install(DIRECTORY ${BUILD_DIR}/lib DESTINATION ${AWESOME_DATA_PATH})
|
||||
install(FILES ${AWE_CONF_FILE_DEFAULT} DESTINATION ${AWESOME_SYSCONFDIR}
|
||||
RENAME ${AWE_CONF_FILE})
|
||||
if(GENERATE_MANPAGES)
|
||||
|
|
|
@ -266,13 +266,12 @@ set(AWESOME_THEMES_PATH ${AWESOME_DATA_PATH}/themes)
|
|||
# }}}
|
||||
|
||||
# {{{ Configure files
|
||||
file(GLOB_RECURSE awesome_lua_configure_files RELATIVE ${SOURCE_DIR} ${SOURCE_DIR}/lib/*.lua.in)
|
||||
set(AWESOME_CONFIGURE_FILES
|
||||
${awesome_lua_configure_files}
|
||||
config.h.in
|
||||
awesomerc.lua.in
|
||||
themes/default.in
|
||||
lib/awful.lua.in
|
||||
lib/beautiful.lua.in
|
||||
lib/tabulous.lua.in
|
||||
awesome-version-internal.h.in
|
||||
awesome.doxygen.in)
|
||||
|
||||
|
|
|
@ -108,8 +108,8 @@ mytaglist.label = awful.widget.taglist.label.all
|
|||
mytasklist = widget({ type = "tasklist", name = "mytasklist" })
|
||||
mytasklist:buttons({
|
||||
button({ }, 1, function (object, c) client.focus = c; c:raise() end),
|
||||
button({ }, 4, function () awful.client.focusbyidx(1) end),
|
||||
button({ }, 5, function () awful.client.focusbyidx(-1) end)
|
||||
button({ }, 4, function () awful.client.focus.byidx(1) end),
|
||||
button({ }, 5, function () awful.client.focus.byidx(-1) end)
|
||||
})
|
||||
mytasklist.label = awful.widget.tasklist.label.currenttags
|
||||
|
||||
|
@ -162,7 +162,7 @@ end
|
|||
|
||||
-- {{{ Mouse bindings
|
||||
awesome.buttons({
|
||||
button({ }, 3, function () awful.spawn(terminal) end),
|
||||
button({ }, 3, function () awful.util.spawn(terminal) end),
|
||||
button({ }, 4, awful.tag.viewnext),
|
||||
button({ }, 5, awful.tag.viewprev)
|
||||
})
|
||||
|
@ -215,7 +215,7 @@ keybinding({ modkey }, "Right", awful.tag.viewnext):add()
|
|||
keybinding({ modkey }, "Escape", awful.tag.history.restore):add()
|
||||
|
||||
-- Standard program
|
||||
keybinding({ modkey }, "Return", function () awful.spawn(terminal) end):add()
|
||||
keybinding({ modkey }, "Return", function () awful.util.spawn(terminal) end):add()
|
||||
|
||||
keybinding({ modkey, "Control" }, "r", awesome.restart):add()
|
||||
keybinding({ modkey, "Shift" }, "q", awesome.quit):add()
|
||||
|
@ -224,8 +224,8 @@ keybinding({ modkey, "Shift" }, "q", awesome.quit):add()
|
|||
keybinding({ modkey }, "m", awful.client.maximize):add()
|
||||
keybinding({ modkey }, "f", function () client.focus.fullscreen = not client.focus.fullscreen end):add()
|
||||
keybinding({ modkey, "Shift" }, "c", function () client.focus:kill() end):add()
|
||||
keybinding({ modkey }, "j", function () awful.client.focusbyidx(1); client.focus:raise() end):add()
|
||||
keybinding({ modkey }, "k", function () awful.client.focusbyidx(-1); client.focus:raise() end):add()
|
||||
keybinding({ modkey }, "j", function () awful.client.focus.byidx(1); client.focus:raise() end):add()
|
||||
keybinding({ modkey }, "k", function () awful.client.focus.byidx(-1); client.focus:raise() end):add()
|
||||
keybinding({ modkey, "Shift" }, "j", function () awful.client.swap(1) end):add()
|
||||
keybinding({ modkey, "Shift" }, "k", function () awful.client.swap(-1) end):add()
|
||||
keybinding({ modkey, "Control" }, "j", function () awful.screen.focus(1) end):add()
|
||||
|
@ -249,7 +249,7 @@ keybinding({ modkey, "Shift" }, "space", function () awful.layout.inc(layouts, -
|
|||
|
||||
-- Prompt
|
||||
keybinding({ modkey }, "F1", function ()
|
||||
awful.prompt.run({ prompt = "Run: " }, mypromptbox, awful.spawn, awful.completion.bash,
|
||||
awful.prompt.run({ prompt = "Run: " }, mypromptbox, awful.util.spawn, awful.completion.bash,
|
||||
os.getenv("HOME") .. "/.cache/awesome/history") end):add()
|
||||
keybinding({ modkey }, "F4", function ()
|
||||
awful.prompt.run({ prompt = "Run Lua code: " }, mypromptbox, awful.eval, awful.prompt.bash,
|
||||
|
|
1858
lib/awful.lua.in
1858
lib/awful.lua.in
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local package = package
|
||||
|
||||
--- Beautiful module for awful
|
||||
module("awful.beautiful")
|
||||
|
||||
-- Exported variable handling theme
|
||||
theme = {}
|
||||
|
||||
--- Set the beautiful theme if any.
|
||||
-- @param The beautiful theme.
|
||||
function register(btheme)
|
||||
if btheme then
|
||||
theme = btheme
|
||||
else
|
||||
theme = {}
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the current registerde them.
|
||||
-- @return The current theme table.
|
||||
function get()
|
||||
return package.loaded.awful.beautiful.theme
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,529 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local hooks = require("awful.hooks")
|
||||
local util = require("awful.util")
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local table = table
|
||||
local math = math
|
||||
local otable = otable
|
||||
local capi =
|
||||
{
|
||||
client = client,
|
||||
mouse = mouse,
|
||||
screen = screen,
|
||||
}
|
||||
|
||||
--- Client module for awful
|
||||
module("awful.client")
|
||||
|
||||
-- Local variable handling theme
|
||||
local theme = {}
|
||||
|
||||
-- mapping of command/completion function
|
||||
local bashcomp_funcs = {}
|
||||
local bashcomp_src = "/etc/bash_completion"
|
||||
|
||||
-- Private data
|
||||
local data = {}
|
||||
data.maximize = otable()
|
||||
data.focus = {}
|
||||
data.urgent = {}
|
||||
data.marked = {}
|
||||
|
||||
-- Urgent functions
|
||||
urgent = {}
|
||||
focus = {}
|
||||
focus.history = {}
|
||||
|
||||
-- User hooks
|
||||
hooks.user.create('marked')
|
||||
hooks.user.create('unmarked')
|
||||
|
||||
--- Get the first client that got the urgent hint.
|
||||
-- @return The first urgent client.
|
||||
function urgent.get()
|
||||
if #data.urgent > 0 then
|
||||
return #data.urgent[1]
|
||||
else
|
||||
-- fallback behaviour: iterate through clients and get the first urgent
|
||||
local clients = capi.client.get()
|
||||
for k, cl in pairs(clients) do
|
||||
if cl.urgent then
|
||||
return cl
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Jump to the client that received the urgent hint first.
|
||||
function urgent.jumpto()
|
||||
local c = urgent.get()
|
||||
if c then
|
||||
local s = capi.client.focus and capi.client.focus.screen or capi.mouse.screen
|
||||
-- focus the screen
|
||||
if s ~= c.screen then
|
||||
capi.mouse.screen = c.screen
|
||||
end
|
||||
-- focus the tag
|
||||
tag.viewonly(c:tags()[1])
|
||||
-- focus the client
|
||||
capi.client.focus = c
|
||||
c:raise()
|
||||
end
|
||||
end
|
||||
|
||||
--- Adds client to urgent stack.
|
||||
-- @param c The client object.
|
||||
-- @param prop The property which is updated.
|
||||
function urgent.add(c, prop)
|
||||
if prop == "urgent" and c.urgent then
|
||||
table.insert(data.urgent, c)
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove client from urgent stack.
|
||||
-- @param c The client object.
|
||||
function urgent.delete(c)
|
||||
for k, cl in ipairs(data.urgent) do
|
||||
if c == cl then
|
||||
table.remove(data.urgent, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove a client from the focus history
|
||||
-- @param c The client that must be removed.
|
||||
function focus.history.delete(c)
|
||||
for k, v in ipairs(data.focus) do
|
||||
if v == c then
|
||||
table.remove(data.focus, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Filter out window that we do not want handled by focus.
|
||||
-- This usually means that desktop, dock and splash windows are
|
||||
-- not registered and cannot get focus.
|
||||
-- @param c A client.
|
||||
-- @return The same client if it's ok, nil otherwise.
|
||||
function focus.filter(c)
|
||||
if c.type == "desktop"
|
||||
or c.type == "dock"
|
||||
or c.type == "splash" then
|
||||
return nil
|
||||
end
|
||||
return c
|
||||
end
|
||||
|
||||
--- Update client focus history.
|
||||
-- @param c The client that has been focused.
|
||||
function focus.history.add(c)
|
||||
if focus.filter(c) then
|
||||
-- Remove the client if its in stack
|
||||
focus.history.delete(c)
|
||||
-- Record the client has latest focused
|
||||
table.insert(data.focus, 1, c)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the latest focused client for a screen in history.
|
||||
-- @param screen The screen number to look for.
|
||||
-- @param idx The index: 0 will return first candidate,
|
||||
-- 1 will return second, etc.
|
||||
-- @return A client.
|
||||
function focus.history.get(screen, idx)
|
||||
-- When this counter is equal to idx, we return the client
|
||||
local counter = 0
|
||||
local vc = visible(screen)
|
||||
for k, c in ipairs(data.focus) do
|
||||
if c.screen == screen then
|
||||
for j, vcc in ipairs(vc) do
|
||||
if vcc == c then
|
||||
if counter == idx then
|
||||
return c
|
||||
end
|
||||
-- We found one, increment the counter only.
|
||||
counter = counter + 1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Argh nobody found in history, give the first one visible if there is one
|
||||
if counter == 0 then
|
||||
return vc[1]
|
||||
end
|
||||
end
|
||||
|
||||
--- Focus the previous client in history.
|
||||
function focus.history.previous()
|
||||
local sel = capi.client.focus
|
||||
local s
|
||||
if sel then
|
||||
s = sel.screen
|
||||
else
|
||||
s = capi.mouse.screen
|
||||
end
|
||||
local c = focus.history.get(s, 1)
|
||||
if c then capi.client.focus = c end
|
||||
end
|
||||
|
||||
--- Get visible clients from a screen.
|
||||
-- @param The screen number, or nil for all screen.
|
||||
-- @return A table with all visible clients.
|
||||
function visible(screen)
|
||||
local cls = capi.client.get(screen)
|
||||
local vcls = {}
|
||||
for k, c in pairs(cls) do
|
||||
if c:isvisible() then
|
||||
table.insert(vcls, c)
|
||||
end
|
||||
end
|
||||
return vcls
|
||||
end
|
||||
|
||||
--- Get a client by its relative index to the focused window.
|
||||
-- @usage Set i to 1 to get next, -1 to get previous.
|
||||
-- @param i The index.
|
||||
-- @param c Optional client.
|
||||
-- @return A client, or nil if no client is available.
|
||||
function next(i, c)
|
||||
-- Get currently focused client
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
-- Get all visible clients
|
||||
local cls = visible(sel.screen)
|
||||
-- Remove all no-normal clients
|
||||
for idx, c in ipairs(cls) do
|
||||
if not focus.filter(c) then
|
||||
table.remove(cls, idx)
|
||||
end
|
||||
end
|
||||
-- Loop upon each client
|
||||
for idx, c in ipairs(cls) do
|
||||
if c == sel then
|
||||
-- Cycle
|
||||
return cls[util.cycle(#cls, idx + i)]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Return true whether client B is in the right direction
|
||||
-- compared to client A.
|
||||
-- @param dir The direction.
|
||||
-- @param cA The first client.
|
||||
-- @param cB The second client.
|
||||
-- @return True if B is in the direction of A.
|
||||
local function is_in_direction(dir, cA, cB)
|
||||
if dir == "up" then
|
||||
return cA['y'] > cB['y']
|
||||
elseif dir == "down" then
|
||||
return cA['y'] < cB['y']
|
||||
elseif dir == "left" then
|
||||
return cA['x'] > cB['x']
|
||||
elseif dir == "right" then
|
||||
return cA['x'] < cB['x']
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Calculate distance between two points.
|
||||
-- i.e: if we want to move to the right, we will take the right border
|
||||
-- of the currently focused client and the left side of the checked client.
|
||||
-- This avoid the focus of an upper client when you move to the right in a
|
||||
-- tilebottom layout with nmaster=2 and 5 clients open, for instance.
|
||||
-- @param dir The direction.
|
||||
-- @param cA The first client.
|
||||
-- @param cB The second client.
|
||||
-- @return The distance between the clients.
|
||||
local function calculate_distance(dir, cA, cB)
|
||||
local xA = cA['x']
|
||||
local xB = cB['x']
|
||||
local yA = cA['y']
|
||||
local yB = cB['y']
|
||||
|
||||
if dir == "up" then
|
||||
yB = yB + cB['height']
|
||||
elseif dir == "down" then
|
||||
yA = yA + cA['height']
|
||||
elseif dir == "left" then
|
||||
xB = xB + cB['width']
|
||||
elseif dir == "right" then
|
||||
xA = xA + cA['width']
|
||||
end
|
||||
|
||||
return math.sqrt(math.pow(xB - xA, 2) + math.pow(yB - yA, 2))
|
||||
end
|
||||
|
||||
--- Focus a client by the given direction.
|
||||
-- @param dir The direction, can be either "up", "down", "left" or "right".
|
||||
-- @param c Optional client.
|
||||
function focus.bydirection(dir, c)
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
local coords = sel:coords()
|
||||
local dist, dist_min
|
||||
local target = nil
|
||||
local cls = visible(sel.screen)
|
||||
|
||||
-- We check each client.
|
||||
for i, c in ipairs(cls) do
|
||||
-- Check coords to see if client is located in the right direction.
|
||||
if is_in_direction(dir, coords, c:coords()) then
|
||||
|
||||
-- Calculate distance between focused client and checked client.
|
||||
dist = calculate_distance(dir, coords, c:coords())
|
||||
|
||||
-- If distance is shorter then keep the client.
|
||||
if not target or dist < dist_min then
|
||||
target = c
|
||||
dist_min = dist
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If we found a client to focus, then do it.
|
||||
if target then
|
||||
capi.client.focus = target
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function focusbyidx(i, c)
|
||||
util.deprecate()
|
||||
return focus.byidx(i, c)
|
||||
end
|
||||
|
||||
--- Focus a client by its relative index.
|
||||
-- @param i The index.
|
||||
-- @param c Optional client.
|
||||
function focus.byidx(i, c)
|
||||
local target = next(i, c)
|
||||
if target then
|
||||
capi.client.focus = target
|
||||
end
|
||||
end
|
||||
|
||||
--- Swap a client by its relative index.
|
||||
-- @param i The index.
|
||||
-- @param c Optional client, otherwise focused one is used.
|
||||
function swap(i, c)
|
||||
local sel = c or capi.client.focus
|
||||
local target = next(i, sel)
|
||||
if target then
|
||||
target:swap(sel)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the master window.
|
||||
-- @param screen Optional screen number, otherwise screen mouse is used.
|
||||
-- @return The master window.
|
||||
function master(screen)
|
||||
local s = screen or capi.mouse.screen
|
||||
return visible(s)[1]
|
||||
end
|
||||
|
||||
-- Set the client as slave: put it at the end of other windows.
|
||||
-- @param c The window to set as slave.
|
||||
-- @return
|
||||
function setslave(c)
|
||||
local cls = visible(c.screen)
|
||||
for k, v in pairs(cls) do
|
||||
c:swap(v)
|
||||
end
|
||||
end
|
||||
|
||||
--- Move/resize a client relative to current coordinates.
|
||||
-- @param x The relative x coordinate.
|
||||
-- @param y The relative y coordinate.
|
||||
-- @param w The relative width.
|
||||
-- @param h The relative height.
|
||||
-- @param c The optional client, otherwise focused one is used.
|
||||
function moveresize(x, y, w, h, c)
|
||||
local sel = c or capi.client.focus
|
||||
local coords = sel:coords()
|
||||
coords['x'] = coords['x'] + x
|
||||
coords['y'] = coords['y'] + y
|
||||
coords['width'] = coords['width'] + w
|
||||
coords['height'] = coords['height'] + h
|
||||
sel:coords(coords)
|
||||
end
|
||||
|
||||
--- Maximize a client to use the full workarea.
|
||||
-- @param c A client, or the focused one if nil.
|
||||
function maximize(c)
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
local ws = capi.screen[sel.screen].workarea
|
||||
ws.width = ws.width - 2 * sel.border_width
|
||||
ws.height = ws.height - 2 * sel.border_width
|
||||
if sel.floating and client.data.maximize[sel] then
|
||||
sel.floating = client.data.maximize[sel].floating
|
||||
if sel.floating then
|
||||
sel:coords(client.data.maximize[sel].coords)
|
||||
end
|
||||
data.maximize[sel] = nil
|
||||
else
|
||||
data.maximize[sel] = { coords = sel:coords(), floating = sel.floating }
|
||||
sel.floating = true
|
||||
sel:coords(ws)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Erase eventual client data in maximize.
|
||||
-- @param c The client.
|
||||
local function maximize_clean(c)
|
||||
data.maximize[c] = nil
|
||||
end
|
||||
|
||||
--- Move a client to a tag.
|
||||
-- @param target The tag to move the client to.
|
||||
-- @param c Optional client to move, otherwise the focused one is used.
|
||||
function movetotag(target, c)
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
-- Check that tag and client screen are identical
|
||||
if sel.screen ~= target.screen then return end
|
||||
sel:tags({ target })
|
||||
end
|
||||
end
|
||||
|
||||
--- Toggle a tag on a client.
|
||||
-- @param target The tag to toggle.
|
||||
-- @param c Optional client to toggle, otherwise the focused one is used.
|
||||
function toggletag(target, c)
|
||||
local sel = c or capi.client.focus
|
||||
-- Check that tag and client screen are identical
|
||||
if sel and sel.screen == target.screen then
|
||||
local tags = sel:tags()
|
||||
if tags[target] then
|
||||
-- If it's the only tag for the window, stop.
|
||||
if #tags == 1 then return end
|
||||
tags[tags[target]] = nil
|
||||
else
|
||||
tags[target] = target
|
||||
end
|
||||
sel:tags(tags)
|
||||
end
|
||||
end
|
||||
|
||||
--- Toggle the floating status of a client.
|
||||
-- @param c Optional client, the focused on if not set.
|
||||
function togglefloating(c)
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
sel.floating = not sel.floating
|
||||
end
|
||||
end
|
||||
|
||||
--- Move a client to a screen. Default is next screen, cycling.
|
||||
-- @param c The client to move.
|
||||
-- @param s The screen number, default to current + 1.
|
||||
function movetoscreen(c, s)
|
||||
local sel = c or capi.client.focus
|
||||
if sel then
|
||||
local sc = capi.screen.count()
|
||||
if not s then
|
||||
s = sel.screen + 1
|
||||
end
|
||||
if s > sc then s = 1 elseif s < 1 then s = sc end
|
||||
sel.screen = s
|
||||
capi.mouse.coords(capi.screen[s].coords)
|
||||
capi.client.focus = sel
|
||||
end
|
||||
end
|
||||
|
||||
--- Mark a client, and then call 'marked' hook.
|
||||
-- @param c The client to mark, the focused one if not specified.
|
||||
-- @return True if the client has been marked. False if the client was already marked.
|
||||
function mark(c)
|
||||
local cl = c or capi.client.focus
|
||||
if cl then
|
||||
for k, v in pairs(data.marked) do
|
||||
if cl == v then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(data.marked, cl)
|
||||
|
||||
-- Call callback
|
||||
hooks.user.call('marked', cl)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
--- Unmark a client and then call 'unmarked' hook.
|
||||
-- @param c The client to unmark, or the focused one if not specified.
|
||||
-- @return True if the client has been unmarked. False if the client was not marked.
|
||||
function unmark(c)
|
||||
local cl = c or capi.client.focus
|
||||
|
||||
for k, v in pairs(data.marked) do
|
||||
if cl == v then
|
||||
table.remove(data.marked, k)
|
||||
hooks.user.call('unmarked', cl)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if a client is marked.
|
||||
-- @param c The client to check, or the focused one otherwise.
|
||||
function ismarked(c)
|
||||
local cl = c or capi.client.focus
|
||||
if cl then
|
||||
for k, v in pairs(data.marked) do
|
||||
if cl == v then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Toggle a client as marked.
|
||||
-- @param c The client to toggle mark.
|
||||
function togglemarked(c)
|
||||
local cl = c or capi.client.focus
|
||||
|
||||
if not client.mark(c) then
|
||||
client.unmark(c)
|
||||
end
|
||||
end
|
||||
|
||||
--- Return the marked clients and empty the marked table.
|
||||
-- @return A table with all marked clients.
|
||||
function getmarked()
|
||||
for k, v in pairs(data.marked) do
|
||||
hooks.user.call('unmarked', v)
|
||||
end
|
||||
|
||||
t = data.marked
|
||||
data.marked = {}
|
||||
return t
|
||||
end
|
||||
|
||||
-- Register standards hooks
|
||||
hooks.focus.register(focus.history.add)
|
||||
hooks.unmanage.register(focus.history.delete)
|
||||
hooks.unmanage.register(maximize_clean)
|
||||
|
||||
hooks.property.register(urgent.add)
|
||||
hooks.focus.register(urgent.delete)
|
||||
hooks.unmanage.register(urgent.delete)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,112 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local io = io
|
||||
local table = table
|
||||
|
||||
--- Completion module for awful
|
||||
module("awful.completion")
|
||||
|
||||
-- mapping of command/completion function
|
||||
local bashcomp_funcs = {}
|
||||
local bashcomp_src = "/etc/bash_completion"
|
||||
|
||||
--- Enable programmable bash completion in awful.completion.bash at the price of
|
||||
-- a slight overhead
|
||||
-- @param src The bash completion source file, /etc/bash_completion by default.
|
||||
function bashcomp_load(src)
|
||||
if src then bashcomp_src = src end
|
||||
local c = io.popen("/usr/bin/env bash -c 'source " .. bashcomp_src .. "; complete -p'")
|
||||
while true do
|
||||
local line = c:read("*line")
|
||||
if not line then break end
|
||||
-- if a bash function is used for completion, register it
|
||||
if line:match(".* -F .*") then
|
||||
bashcomp_funcs[line:gsub(".* (%S+)$","%1")] = line:gsub(".*-F +(%S+) .*$", "%1")
|
||||
end
|
||||
end
|
||||
c:close()
|
||||
end
|
||||
|
||||
--- Use bash completion system to complete command and filename.
|
||||
-- @param command The command line.
|
||||
-- @param cur_pos The cursor position.
|
||||
-- @param ncomp The element number to complete.
|
||||
-- @return The new command and the new cursor position.
|
||||
function bash(command, cur_pos, ncomp)
|
||||
local wstart = 1
|
||||
local wend = 1
|
||||
local words = {}
|
||||
local cword_index = 0
|
||||
local cword_start = 0
|
||||
local cword_end = 0
|
||||
local i = 1
|
||||
local comptype = "file"
|
||||
|
||||
-- do nothing if we are on a letter, i.e. not at len + 1 or on a space
|
||||
if cur_pos ~= #command + 1 and command:sub(cur_pos, cur_pos) ~= " " then
|
||||
return command, cur_pos
|
||||
elseif #command == 0 then
|
||||
return command, cur_pos
|
||||
end
|
||||
|
||||
while wend <= #command do
|
||||
wend = command:find(" ", wstart)
|
||||
if not wend then wend = #command + 1 end
|
||||
table.insert(words, command:sub(wstart, wend - 1))
|
||||
if cur_pos >= wstart and cur_pos <= wend + 1 then
|
||||
cword_start = wstart
|
||||
cword_end = wend
|
||||
cword_index = i
|
||||
end
|
||||
wstart = wend + 1
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
if cword_index == 1 then
|
||||
comptype = "command"
|
||||
end
|
||||
|
||||
local bash_cmd
|
||||
if bashcomp_funcs[words[1]] then
|
||||
-- fairly complex command with inline bash script to get the possible completions
|
||||
bash_cmd = "/usr/bin/env bash -c 'source " .. bashcomp_src .. "; " ..
|
||||
"__print_completions() { for ((i=0;i<${#COMPREPLY[*]};i++)); do echo ${COMPREPLY[i]}; done }; " ..
|
||||
"COMP_WORDS=(" .. command .."); COMP_LINE=\"" .. command .. "\"; " ..
|
||||
"COMP_COUNT=" .. cur_pos .. "; COMP_CWORD=" .. cword_index-1 .. "; " ..
|
||||
bashcomp_funcs[words[1]] .. "; __print_completions | sort -u'"
|
||||
else
|
||||
bash_cmd = "/usr/bin/env bash -c 'compgen -A " .. comptype .. " " .. words[cword_index] .. "'"
|
||||
end
|
||||
local c = io.popen(bash_cmd)
|
||||
local output = {}
|
||||
i = 0
|
||||
while true do
|
||||
local line = c:read("*line")
|
||||
if not line then break end
|
||||
table.insert(output, line)
|
||||
end
|
||||
|
||||
c:close()
|
||||
|
||||
-- no completion, return
|
||||
if #output == 0 then
|
||||
return command, cur_pos
|
||||
end
|
||||
|
||||
-- cycle
|
||||
while ncomp > #output do
|
||||
ncomp = ncomp - #output
|
||||
end
|
||||
|
||||
local str = command:sub(1, cword_start - 1) .. output[ncomp] .. command:sub(cword_end)
|
||||
cur_pos = cword_end + #output[ncomp] + 1
|
||||
|
||||
return str, cur_pos
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,125 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local pairs = pairs
|
||||
local table = table
|
||||
local ipairs = ipairs
|
||||
local type = type
|
||||
local math = math
|
||||
local capi =
|
||||
{
|
||||
hooks = hooks
|
||||
}
|
||||
|
||||
--- Hooks module for awful
|
||||
module("awful.hooks")
|
||||
|
||||
-- User hook functions
|
||||
user = {}
|
||||
|
||||
--- Create a new userhook (for external libs).
|
||||
-- @param name Hook name.
|
||||
function user.create(name)
|
||||
_M[name] = {}
|
||||
_M[name].callbacks = {}
|
||||
_M[name].register = function (f)
|
||||
table.insert(_M[name].callbacks, f)
|
||||
end
|
||||
_M[name].unregister = function (f)
|
||||
for k, h in ipairs(_M[name].callbacks) do
|
||||
if h == f then
|
||||
table.remove(_M[name].callbacks, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Call a created userhook (for external libs).
|
||||
-- @param name Hook name.
|
||||
function user.call(name, ...)
|
||||
for name, callback in pairs(_M[name].callbacks) do
|
||||
callback(...)
|
||||
end
|
||||
end
|
||||
|
||||
-- Autodeclare awful.hooks.* functions
|
||||
-- mapped to awesome hooks.* functions
|
||||
for name, hook in pairs(capi.hooks) do
|
||||
if name ~= 'timer' then
|
||||
_M[name] = {}
|
||||
_M[name].register = function (f)
|
||||
if not _M[name].callbacks then
|
||||
_M[name].callbacks = {}
|
||||
hook(function (...)
|
||||
for i, callback in ipairs(_M[name].callbacks) do
|
||||
callback(...)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
table.insert(_M[name].callbacks, f)
|
||||
end
|
||||
_M[name].unregister = function (f)
|
||||
if _M[name].callbacks then
|
||||
for k, h in ipairs(_M[name].callbacks) do
|
||||
if h == f then
|
||||
table.remove(_M[name].callbacks, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
_M[name] = {}
|
||||
_M[name].register = function (time, f, runnow)
|
||||
if type(time) ~= 'number' or type(f) ~= 'function' or time <= 0 then
|
||||
return
|
||||
end
|
||||
local new_timer
|
||||
if _M[name].timer then
|
||||
-- Take the smallest between current and new
|
||||
new_timer = math.min(time, _M[name].timer)
|
||||
else
|
||||
new_timer = time
|
||||
end
|
||||
if not _M[name].callbacks then
|
||||
_M[name].callbacks = {}
|
||||
end
|
||||
if _M[name].timer ~= new_timer then
|
||||
_M[name].timer = new_timer
|
||||
hook(_M[name].timer, function (...)
|
||||
for i, callback in ipairs(_M[name].callbacks) do
|
||||
callback['counter'] = callback['counter'] + _M[name].timer
|
||||
if callback['counter'] >= callback['timer'] then
|
||||
callback['callback'](...)
|
||||
callback['counter'] = 0
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
if runnow then
|
||||
table.insert(_M[name].callbacks, { callback = f, timer = time, counter = time })
|
||||
else
|
||||
table.insert(_M[name].callbacks, { callback = f, timer = time, counter = 0 })
|
||||
end
|
||||
end
|
||||
_M[name].unregister = function (f)
|
||||
if _M[name].callbacks then
|
||||
for k, h in ipairs(_M[name].callbacks) do
|
||||
if h.callback == f then
|
||||
table.remove(_M[name].callbacks, k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,23 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local beautiful = require("awful.beautiful")
|
||||
local client = require("awful.client")
|
||||
local completion = require("awful.completion")
|
||||
local hooks = require("awful.hooks")
|
||||
local layout = require("awful.layout")
|
||||
local placement = require("awful.placement")
|
||||
local prompt = require("awful.prompt")
|
||||
local screen = require("awful.screen")
|
||||
local tag = require("awful.tag")
|
||||
local titlebar = require("awful.titlebar")
|
||||
local util = require("awful.util")
|
||||
local widget = require("awful.widget")
|
||||
|
||||
--- awful: AWesome Functions very UsefuL
|
||||
module("awful")
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,53 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local ipairs = ipairs
|
||||
local tag = require("awful.tag")
|
||||
|
||||
--- Layout module for awful
|
||||
module("awful.layout")
|
||||
|
||||
--- Get the current layout name.
|
||||
-- @param screen The screen number.
|
||||
function get(screen)
|
||||
local t = tag.selected(screen)
|
||||
if t then
|
||||
return t.layout
|
||||
end
|
||||
end
|
||||
|
||||
--- Change the layout of the current tag.
|
||||
-- @param layouts A table of layouts.
|
||||
-- @param i Relative index.
|
||||
function inc(layouts, i)
|
||||
local t = tag.selected()
|
||||
local number_of_layouts = 0
|
||||
local rev_layouts = {}
|
||||
for i, v in ipairs(layouts) do
|
||||
rev_layouts[v] = i
|
||||
number_of_layouts = number_of_layouts + 1
|
||||
end
|
||||
if t then
|
||||
local cur_layout = get()
|
||||
local new_layout_index = (rev_layouts[cur_layout] + i) % number_of_layouts
|
||||
if new_layout_index == 0 then
|
||||
new_layout_index = number_of_layouts
|
||||
end
|
||||
t.layout = layouts[new_layout_index]
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the layout of the current tag by name.
|
||||
-- @param layout Layout name.
|
||||
function set(layout)
|
||||
local t = tag.selected()
|
||||
if t then
|
||||
t.layout = layout
|
||||
end
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,175 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local ipairs = ipairs
|
||||
local pairs = pairs
|
||||
local math = math
|
||||
local table = table
|
||||
local capi =
|
||||
{
|
||||
screen = screen,
|
||||
mouse = mouse,
|
||||
}
|
||||
local client = require("awful.client")
|
||||
local layout = require("awful.layout")
|
||||
|
||||
--- Placement module for awful
|
||||
module("awful.placement")
|
||||
|
||||
--- Check if an area intersect another area.
|
||||
-- @param a The area.
|
||||
-- @param b The other area.
|
||||
-- @return True if they intersect, false otherwise.
|
||||
local function area_intersect_area(a, b)
|
||||
return (b.x < a.x + a.width
|
||||
and b.x + b.width > a.x
|
||||
and b.y < a.y + a.height
|
||||
and b.y + b.height > a.y)
|
||||
end
|
||||
|
||||
--- Get the intersect area between a and b.
|
||||
-- @param a The area.
|
||||
-- @param b The other area.
|
||||
-- @return The intersect area.
|
||||
local function area_intersect_area_get(a, b)
|
||||
local g = {}
|
||||
g.x = math.max(a.x, b.x)
|
||||
g.y = math.max(a.y, b.y)
|
||||
g.width = math.min(a.x + a.width, b.x + b.width) - g.x
|
||||
g.height = math.min(a.y + a.height, b.y + b.height) - g.y
|
||||
return g
|
||||
end
|
||||
|
||||
--- Remove an area from a list, splitting the space between several area that
|
||||
-- can overlap.
|
||||
-- @param areas Table of areas.
|
||||
-- @param elem Area to remove.
|
||||
-- @return The new area list.
|
||||
local function area_remove(areas, elem)
|
||||
local newareas = areas
|
||||
for i, r in ipairs(areas) do
|
||||
-- Check if the 'elem' intersect
|
||||
if area_intersect_area(r, elem) then
|
||||
-- It does? remove it
|
||||
table.remove(areas, i)
|
||||
local inter = area_intersect_area_get(r, elem)
|
||||
|
||||
if inter.x > r.x then
|
||||
table.insert(newareas, {
|
||||
x = r.x,
|
||||
y = r.y,
|
||||
width = inter.x - r.x,
|
||||
height = r.height
|
||||
})
|
||||
end
|
||||
|
||||
if inter.y > r.y then
|
||||
table.insert(newareas, {
|
||||
x = r.x,
|
||||
y = r.y,
|
||||
width = r.width,
|
||||
height = inter.y - r.y
|
||||
})
|
||||
end
|
||||
|
||||
if inter.x + inter.width < r.x + r.width then
|
||||
table.insert(newareas, {
|
||||
x = inter.x + inter.width,
|
||||
y = r.y,
|
||||
width = (r.x + r.width) - (inter.x + inter.width),
|
||||
height = r.height
|
||||
})
|
||||
end
|
||||
|
||||
if inter.y + inter.height < r.y + r.height then
|
||||
table.insert(newareas, {
|
||||
x = r.x,
|
||||
y = inter.y + inter.height,
|
||||
width = r.width,
|
||||
height = (r.y + r.height) - (inter.y + inter.height)
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return newareas
|
||||
end
|
||||
|
||||
--- Place the client without it being outside the screen.
|
||||
-- @param c The client.
|
||||
function no_offscreen(c)
|
||||
local geometry = c:fullcoords()
|
||||
local screen_geometry = capi.screen[c.screen].workarea
|
||||
|
||||
if geometry.x + geometry.width > screen_geometry.x + screen_geometry.width then
|
||||
geometry.x = screen_geometry.x + screen_geometry.width - geometry.width
|
||||
elseif geometry.x < screen_geometry.x then
|
||||
geometry.x = screen_geometry.x
|
||||
end
|
||||
|
||||
if geometry.y + geometry.height > screen_geometry.y + screen_geometry.height then
|
||||
geometry.y = screen_geometry.y + screen_geometry.height - geometry.height
|
||||
elseif geometry.y < screen_geometry.y then
|
||||
geometry.y = screen_geometry.y
|
||||
end
|
||||
|
||||
c:fullcoords(geometry)
|
||||
end
|
||||
|
||||
--- Place the client where there's place available with minimum overlap.
|
||||
-- @param c The client.
|
||||
function no_overlap(c)
|
||||
local cls = client.visible(c.screen)
|
||||
local layout = layout.get()
|
||||
local areas = { capi.screen[c.screen].workarea }
|
||||
local coords = c:coords()
|
||||
local fullcoords = c:fullcoords()
|
||||
for i, cl in pairs(cls) do
|
||||
if cl ~= c and (cl.floating or layout == "floating") then
|
||||
areas = area_remove(areas, cl:fullcoords())
|
||||
end
|
||||
end
|
||||
|
||||
-- Look for available space
|
||||
local found = false
|
||||
local new = { x = coords.x, y = coords.y, width = 0, height = 0 }
|
||||
for i, r in ipairs(areas) do
|
||||
if r.width >= fullcoords.width
|
||||
and r.height >= fullcoords.height
|
||||
and r.width * r.height > new.width * new.height then
|
||||
found = true
|
||||
new = r
|
||||
end
|
||||
end
|
||||
|
||||
-- We did not foudn an area with enough space for our size:
|
||||
-- just take the biggest available one and go in
|
||||
if not found then
|
||||
for i, r in ipairs(areas) do
|
||||
if r.width * r.height > new.width * new.height then
|
||||
new = r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Restore height and width
|
||||
new.width = coords.width
|
||||
new.height = coords.height
|
||||
|
||||
c:coords(new)
|
||||
end
|
||||
|
||||
--- Place the client under the mouse.
|
||||
-- @param c The client.
|
||||
function under_mouse(c)
|
||||
local c_coords = c:coords()
|
||||
local m_coords = capi.mouse.coords()
|
||||
c:coords({ x = m_coords.x - c_coords.width / 2,
|
||||
y = m_coords.y - c_coords.height / 2 })
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,305 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local assert = assert
|
||||
local io = io
|
||||
local table = table
|
||||
local capi =
|
||||
{
|
||||
keygrabber = keygrabber
|
||||
}
|
||||
local util = require("awful.util")
|
||||
local beautiful = require("awful.beautiful")
|
||||
|
||||
--- Prompt module for awful
|
||||
module("awful.prompt")
|
||||
|
||||
--- Private data
|
||||
local data = {}
|
||||
data.history = {}
|
||||
|
||||
--- Load history file in history table
|
||||
-- @param id The data.history identifier which is the path to the filename
|
||||
-- @param max Optional parameter, the maximum number of entries in file
|
||||
local function history_check_load(id, max)
|
||||
if id and id ~= ""
|
||||
and not data.history[id] then
|
||||
data.history[id] = { max = 50, table = {} }
|
||||
|
||||
if max then
|
||||
data.history[id].max = max
|
||||
end
|
||||
|
||||
local f = io.open(id, "r")
|
||||
|
||||
-- Read history file
|
||||
if f then
|
||||
for line in f:lines() do
|
||||
table.insert(data.history[id].table, line)
|
||||
if #data.history[id].table >= data.history[id].max then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Save history table in history file
|
||||
-- @param id The data.history identifier
|
||||
local function history_save(id)
|
||||
if data.history[id] then
|
||||
local f = io.open(id, "w")
|
||||
if not f then
|
||||
local i = 0
|
||||
for d in id:gmatch(".-/") do
|
||||
i = i + #d
|
||||
end
|
||||
util.mkdir(id:sub(1, i - 1))
|
||||
f = assert(io.open(id, "w"))
|
||||
end
|
||||
for i = 1, math.min(#data.history[id].table, data.history[id].max) do
|
||||
f:write(data.history[id].table[i] .. "\n")
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
--- Return the number of items in history table regarding the id
|
||||
-- @param id The data.history identifier
|
||||
-- @return the number of items in history table, -1 if history is disabled
|
||||
local function history_items(id)
|
||||
if data.history[id] then
|
||||
return #data.history[id].table
|
||||
else
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
--- Add an entry to the history file
|
||||
-- @param id The data.history identifier
|
||||
-- @param command The command to add
|
||||
local function history_add(id, command)
|
||||
if data.history[id] then
|
||||
if command ~= ""
|
||||
and command ~= data.history[id].table[#data.history[id].table] then
|
||||
table.insert(data.history[id].table, command)
|
||||
|
||||
-- Do not exceed our max_cmd
|
||||
if #data.history[id].table > data.history[id].max then
|
||||
table.remove(data.history[id].table, 1)
|
||||
end
|
||||
|
||||
history_save(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Draw the prompt text with a cursor.
|
||||
-- @param text The text.
|
||||
-- @param text_color The text color.
|
||||
-- @param cursor_color The cursor color.
|
||||
-- @param cursor_pos The cursor position.
|
||||
local function prompt_text_with_cursor(text, text_color, cursor_color, cursor_pos)
|
||||
local char
|
||||
if not text then text = "" end
|
||||
if #text < cursor_pos then
|
||||
char = " "
|
||||
else
|
||||
char = util.escape(text:sub(cursor_pos, cursor_pos))
|
||||
end
|
||||
local text_start = util.escape(text:sub(1, cursor_pos - 1))
|
||||
local text_end = util.escape(text:sub(cursor_pos + 1))
|
||||
return text_start .. "<span background=\"" .. util.color_strip_alpha(cursor_color) .. "\" foreground=\"" .. util.color_strip_alpha(text_color) .. "\">" .. char .. "</span>" .. text_end
|
||||
end
|
||||
|
||||
--- Run a prompt in a box.
|
||||
-- @param args A table with optional arguments: fg_cursor, bg_cursor, prompt.
|
||||
-- @param textbox The textbox to use for the prompt.
|
||||
-- @param exe_callback The callback function to call with command as argument when finished.
|
||||
-- @param completion_callback The callback function to call to get completion.
|
||||
-- @param history_path Optional parameter: file path where the history should be saved, set nil to disable history
|
||||
-- @param history_max Optional parameter: set the maximum entries in history file, 50 by default
|
||||
-- @param done_callback Optional parameter: the callback function to always call without arguments, regardless of whether the prompt was cancelled.
|
||||
function run(args, textbox, exe_callback, completion_callback, history_path, history_max, done_callback)
|
||||
local theme = beautiful.get()
|
||||
if not args then args = {} end
|
||||
local command = ""
|
||||
local command_before_comp
|
||||
local cur_pos_before_comp
|
||||
local prettyprompt = args.prompt or ""
|
||||
local inv_col = args.fg_cursor or theme.fg_focus or "black"
|
||||
local cur_col = args.bg_cursor or theme.bg_focus or "white"
|
||||
|
||||
history_check_load(history_path, history_max)
|
||||
local history_index = history_items(history_path) + 1
|
||||
-- The cursor position
|
||||
local cur_pos = 1
|
||||
-- The completion element to use on completion request.
|
||||
local ncomp = 1
|
||||
if not textbox or not exe_callback then
|
||||
return
|
||||
end
|
||||
textbox.text = prettyprompt .. prompt_text_with_cursor(text, inv_col, cur_col, cur_pos)
|
||||
capi.keygrabber.run(
|
||||
function (mod, key)
|
||||
-- Get out cases
|
||||
if mod.Control then
|
||||
if key == "c" or key == "g" then
|
||||
textbox.text = ""
|
||||
if done_callback then done_callback() end
|
||||
return false
|
||||
elseif key == "j" or key == "m" then
|
||||
textbox.text = ""
|
||||
exec_callback(command)
|
||||
if done_callback then done_callback() end
|
||||
return false
|
||||
end
|
||||
else
|
||||
if key == "Return" then
|
||||
textbox.text = ""
|
||||
data.history_add(history_path, command)
|
||||
exe_callback(command)
|
||||
if done_callback then done_callback() end
|
||||
return false
|
||||
elseif key == "Escape" then
|
||||
textbox.text = ""
|
||||
if done_callback then done_callback() end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Control cases
|
||||
if mod.Control then
|
||||
if key == "a" then
|
||||
cur_pos = 1
|
||||
elseif key == "b" then
|
||||
if cur_pos > 1 then
|
||||
cur_pos = cur_pos - 1
|
||||
end
|
||||
elseif key == "d" then
|
||||
if cur_pos <= #command then
|
||||
command = command:sub(1, cur_pos - 1) .. command:sub(cur_pos + 1)
|
||||
end
|
||||
elseif key == "e" then
|
||||
cur_pos = #command + 1
|
||||
elseif key == "f" then
|
||||
if cur_pos <= #command then
|
||||
cur_pos = cur_pos + 1
|
||||
end
|
||||
elseif key == "h" then
|
||||
if cur_pos > 1 then
|
||||
command = command:sub(1, cur_pos - 2) .. command:sub(cur_pos)
|
||||
cur_pos = cur_pos - 1
|
||||
end
|
||||
elseif key == "k" then
|
||||
command = command:sub(1, cur_pos - 1)
|
||||
elseif key == "u" then
|
||||
command = command:sub(cur_pos, #command)
|
||||
cur_pos = 1
|
||||
elseif key == "w" then
|
||||
local wstart = 1
|
||||
local wend = 1
|
||||
local cword_start = 1
|
||||
local cword_end = 1
|
||||
while wend < cur_pos do
|
||||
wend = command:find(" ", wstart)
|
||||
if not wend then wend = #command + 1 end
|
||||
if cur_pos >= wstart and cur_pos <= wend + 1 then
|
||||
cword_start = wstart
|
||||
cword_end = cur_pos - 1
|
||||
break
|
||||
end
|
||||
wstart = wend + 1
|
||||
end
|
||||
command = command:sub(1, cword_start - 1) .. command:sub(cword_end + 1)
|
||||
cur_pos = cword_start
|
||||
end
|
||||
else
|
||||
if completion_callback then
|
||||
-- That's tab
|
||||
if key:byte() == 9 or key == "ISO_Left_Tab" then
|
||||
if key == "ISO_Left_Tab" then
|
||||
if ncomp == 1 then return true end
|
||||
if ncomp == 2 then
|
||||
command = command_before_comp
|
||||
textbox.text = prettyprompt .. prompt_text_with_cursor(command_before_comp, inv_col, cur_col, cur_pos)
|
||||
return true
|
||||
end
|
||||
|
||||
ncomp = ncomp - 2
|
||||
elseif ncomp == 1 then
|
||||
command_before_comp = command
|
||||
cur_pos_before_comp = cur_pos
|
||||
end
|
||||
command, cur_pos = completion_callback(command_before_comp, cur_pos_before_comp, ncomp)
|
||||
ncomp = ncomp + 1
|
||||
key = ""
|
||||
else
|
||||
ncomp = 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Typin cases
|
||||
if key == "Home" then
|
||||
cur_pos = 1
|
||||
elseif key == "End" then
|
||||
cur_pos = #command + 1
|
||||
elseif key == "BackSpace" then
|
||||
if cur_pos > 1 then
|
||||
command = command:sub(1, cur_pos - 2) .. command:sub(cur_pos)
|
||||
cur_pos = cur_pos - 1
|
||||
end
|
||||
-- That's DEL
|
||||
elseif key:byte() == 127 then
|
||||
command = command:sub(1, cur_pos - 1) .. command:sub(cur_pos + 1)
|
||||
elseif key == "Left" then
|
||||
cur_pos = cur_pos - 1
|
||||
elseif key == "Right" then
|
||||
cur_pos = cur_pos + 1
|
||||
elseif key == "Up" then
|
||||
if history_index > 1 then
|
||||
history_index = history_index - 1
|
||||
|
||||
command = data.history[history_path].table[history_index]
|
||||
cur_pos = #command + 2
|
||||
end
|
||||
elseif key == "Down" then
|
||||
if history_index < history_items(history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
command = data.history[history_path].table[history_index]
|
||||
cur_pos = #command + 2
|
||||
elseif history_index == history_items(history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
command = ""
|
||||
cur_pos = 1
|
||||
end
|
||||
else
|
||||
-- len() is UTF-8 aware but #key is not,
|
||||
-- so check that we have one UTF-8 char but advance the cursor of # position
|
||||
if key:len() == 1 then
|
||||
command = command:sub(1, cur_pos - 1) .. key .. command:sub(cur_pos)
|
||||
cur_pos = cur_pos + #key
|
||||
end
|
||||
end
|
||||
if cur_pos < 1 then
|
||||
cur_pos = 1
|
||||
elseif cur_pos > #command + 1 then
|
||||
cur_pos = #command + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Update textbox
|
||||
textbox.text = prettyprompt .. prompt_text_with_cursor(command, inv_col, cur_col, cur_pos)
|
||||
|
||||
return true
|
||||
end)
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,30 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local capi =
|
||||
{
|
||||
mouse = mouse,
|
||||
screen = screen,
|
||||
client = client
|
||||
}
|
||||
local util = require("awful.util")
|
||||
local client = require("awful.client")
|
||||
|
||||
--- Screen module for awful
|
||||
module("awful.screen")
|
||||
|
||||
--- Give the focus to a screen, and move pointer.
|
||||
-- @param Screen number.
|
||||
function focus(i)
|
||||
local s = util.cycle(capi.screen.count(), capi.mouse.screen + i)
|
||||
local c = client.focus.history.get(s, 0)
|
||||
if c then capi.client.focus = c end
|
||||
-- Move the mouse on the screen
|
||||
capi.mouse.screen = s
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,206 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local hooks = require("awful.hooks")
|
||||
local util = require("awful.util")
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local capi =
|
||||
{
|
||||
screen = screen,
|
||||
mouse = mouse
|
||||
}
|
||||
|
||||
--- Tag module for awful
|
||||
module("awful.tag")
|
||||
|
||||
-- Private data
|
||||
local data = {}
|
||||
data.history = {}
|
||||
data.history.past = {}
|
||||
data.history.current = {}
|
||||
|
||||
-- History functions
|
||||
history = {}
|
||||
|
||||
--- Compare 2 tables of tags.
|
||||
-- @param a The first table.
|
||||
-- @param b The second table of tags.
|
||||
-- @return True if the tables are identical, false otherwise.
|
||||
local function compare_select(a, b)
|
||||
if not a or not b then
|
||||
return false
|
||||
end
|
||||
-- Quick size comparison
|
||||
if #a ~= #b then
|
||||
return false
|
||||
end
|
||||
for ka, va in pairs(a) do
|
||||
if b[ka] ~= va.selected then
|
||||
return false
|
||||
end
|
||||
end
|
||||
for kb, vb in pairs(b) do
|
||||
if a[kb].selected ~= vb then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Update the tag history.
|
||||
-- @param screen The screen number.
|
||||
function history.update(screen)
|
||||
local curtags = capi.screen[screen]:tags()
|
||||
if not compare_select(curtags, data.history.current[screen]) then
|
||||
data.history.past[screen] = data.history.current[screen]
|
||||
data.history.current[screen] = {}
|
||||
for k, v in ipairs(curtags) do
|
||||
data.history.current[screen][k] = v.selected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Revert tag history.
|
||||
-- @param screen The screen number.
|
||||
function history.restore(screen)
|
||||
local s = screen or capi.mouse.screen
|
||||
local tags = capi.screen[s]:tags()
|
||||
for k, t in pairs(tags) do
|
||||
t.selected = data.history.past[s][k]
|
||||
end
|
||||
end
|
||||
|
||||
--- Return a table with all visible tags
|
||||
-- @param s Screen number.
|
||||
-- @return A table with all selected tags.
|
||||
function selectedlist(s)
|
||||
local screen = s or capi.mouse.screen
|
||||
local tags = capi.screen[screen]:tags()
|
||||
local vtags = {}
|
||||
for i, t in pairs(tags) do
|
||||
if t.selected then
|
||||
vtags[#vtags + 1] = t
|
||||
end
|
||||
end
|
||||
return vtags
|
||||
end
|
||||
|
||||
--- Return only the first visible tag.
|
||||
-- @param s Screen number.
|
||||
function selected(s)
|
||||
return selectedlist(s)[1]
|
||||
end
|
||||
|
||||
--- Set master width factor.
|
||||
-- @param mwfact Master width factor.
|
||||
function setmwfact(mwfact)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.mwfact = mwfact
|
||||
end
|
||||
end
|
||||
|
||||
--- Increase master width factor.
|
||||
-- @param add Value to add to master width factor.
|
||||
function incmwfact(add)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.mwfact = t.mwfact + add
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the number of master windows.
|
||||
-- @param nmaster The number of master windows.
|
||||
function setnmaster(nmaster)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.nmaster = nmaster
|
||||
end
|
||||
end
|
||||
|
||||
--- Increase the number of master windows.
|
||||
-- @param add Value to add to number of master windows.
|
||||
function incnmaster(add)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.nmaster = t.nmaster + add
|
||||
end
|
||||
end
|
||||
|
||||
--- Set number of column windows.
|
||||
-- @param ncol The number of column.
|
||||
function setncol(ncol)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.ncol = ncol
|
||||
end
|
||||
end
|
||||
|
||||
--- Increase number of column windows.
|
||||
-- @param add Value to add to number of column windows.
|
||||
function incncol(add)
|
||||
local t = selected()
|
||||
if t then
|
||||
t.ncol = t.ncol + add
|
||||
end
|
||||
end
|
||||
|
||||
--- View no tag.
|
||||
-- @param Optional screen number.
|
||||
function viewnone(screen)
|
||||
local tags = capi.screen[screen or capi.mouse.screen]:tags()
|
||||
for i, t in pairs(tags) do
|
||||
t.selected = false
|
||||
end
|
||||
end
|
||||
|
||||
--- View a tag by its index.
|
||||
-- @param i The relative index to see.
|
||||
-- @param screen Optional screen number.
|
||||
function viewidx(i, screen)
|
||||
local tags = capi.screen[screen or capi.mouse.screen]:tags()
|
||||
local sel = selected()
|
||||
viewnone()
|
||||
for k, t in ipairs(tags) do
|
||||
if t == sel then
|
||||
tags[util.cycle(#tags, k + i)].selected = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- View next tag. This is the same as tag.viewidx(1).
|
||||
function viewnext()
|
||||
return viewidx(1)
|
||||
end
|
||||
|
||||
--- View previous tag. This is the same a tag.viewidx(-1).
|
||||
function viewprev()
|
||||
return viewidx(-1)
|
||||
end
|
||||
|
||||
--- View only a tag.
|
||||
-- @param t The tag object.
|
||||
function viewonly(t)
|
||||
viewnone(t.screen)
|
||||
t.selected = true
|
||||
end
|
||||
|
||||
--- View only a set of tags.
|
||||
-- @param tags A table with tags to view only.
|
||||
-- @param screen Optional screen number of the tags.
|
||||
function viewmore(tags, screen)
|
||||
viewnone(screen)
|
||||
for i, t in pairs(tags) do
|
||||
t.selected = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Register standards hooks
|
||||
hooks.arrange.register(history.update)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,163 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local math = math
|
||||
local ipairs = ipairs
|
||||
local otable = otable
|
||||
local capi =
|
||||
{
|
||||
wibox = wibox,
|
||||
widget = widget,
|
||||
button = button,
|
||||
client = client,
|
||||
}
|
||||
local hooks = require("awful.hooks")
|
||||
local util = require("awful.util")
|
||||
|
||||
--- Titlebar module for awful
|
||||
module("awful.titlebar")
|
||||
|
||||
-- Privata data
|
||||
local data = otable()
|
||||
|
||||
--- Create a standard titlebar.
|
||||
-- @param c The client.
|
||||
-- @param args Arguments.
|
||||
-- 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" then return end
|
||||
if not args then args = {} end
|
||||
-- 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
|
||||
|
||||
-- Built args
|
||||
local targs = {}
|
||||
if args.fg then targs.fg = args.fg end
|
||||
if args.bg then targs.bg = args.bg end
|
||||
local tb = capi.wibox(targs)
|
||||
|
||||
local title = capi.widget({ type = "textbox", name = "title", align = "flex" })
|
||||
title.text = " " .. util.escape(c.name) .. " "
|
||||
local bts =
|
||||
{
|
||||
capi.button({ }, 1, function (t) t.client:mouse_move() end),
|
||||
capi.button({ args.modkey }, 3, function (t) t.client:mouse_resize() end)
|
||||
}
|
||||
title:buttons(bts)
|
||||
|
||||
local appicon = capi.widget({ type = "imagebox", name = "appicon", align = "left" })
|
||||
appicon.image = c.icon
|
||||
|
||||
if theme.titlebar_close_button == "true" then
|
||||
local closef = widget.button({ name = "closef", align = "right",
|
||||
image = theme.titlebar_close_button_focus
|
||||
or theme.titlebar_close_button_img_focus
|
||||
or "@AWESOME_ICON_PATH@/titlebar/closer.png" })
|
||||
local close = widget.button({ name = "close", align = "right",
|
||||
image = theme.titlebar_close_button_normal
|
||||
or theme.titlebar_close_button_img_normal
|
||||
or "@AWESOME_ICON_PATH@/titlebar/close.png" })
|
||||
|
||||
-- Bind kill button
|
||||
local b = capi.button({ }, 1, nil, function (t) t.client:kill() end)
|
||||
local bts = closef:buttons()
|
||||
bts[#bts + 1] = b
|
||||
closef:buttons(bts)
|
||||
|
||||
bts = close:buttons()
|
||||
bts[#bts + 1] = b
|
||||
close:buttons(bts)
|
||||
|
||||
tb:widgets({
|
||||
appicon,
|
||||
title,
|
||||
closef, close
|
||||
})
|
||||
else
|
||||
tb:widgets({
|
||||
appicon,
|
||||
title
|
||||
})
|
||||
end
|
||||
|
||||
c.titlebar = tb
|
||||
|
||||
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()
|
||||
local title, close, closef
|
||||
for k, v in ipairs(widgets) do
|
||||
if v.name == "title" then title = v
|
||||
elseif v.name == "close" then close = v
|
||||
elseif v.name == "closef" then closef = v
|
||||
elseif v.name == "appicon" then appicon = v end
|
||||
if title and close and closef and appicon then break end
|
||||
end
|
||||
if prop == "name" then
|
||||
if title then
|
||||
title.text = " " .. util.escape(c.name) .. " "
|
||||
end
|
||||
elseif prop == "icon" then
|
||||
if appicon then
|
||||
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:coords().width + 2 * c.border_width)
|
||||
c.titlebar:geometry({ width = w })
|
||||
else
|
||||
local w = math.min(data[c].width, c:coords().height + 2 * c.border_width)
|
||||
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 closef then closef.visible = true end
|
||||
if close then close.visible = false end
|
||||
else
|
||||
c.titlebar.fg = data[c].fg
|
||||
c.titlebar.bg = data[c].bg
|
||||
if closef then closef.visible = false end
|
||||
if close then close.visible = true end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove a titlebar from a client.
|
||||
-- @param c The client.
|
||||
function remove(c)
|
||||
c.titlebar = nil
|
||||
data[c] = nil
|
||||
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
|
|
@ -0,0 +1,112 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local os = os
|
||||
local io = io
|
||||
local assert = assert
|
||||
local loadstring = loadstring
|
||||
local debug = debug
|
||||
local print = print
|
||||
local capi =
|
||||
{
|
||||
awesome = awesome,
|
||||
mouse = mouse
|
||||
}
|
||||
|
||||
--- Utility module for awful
|
||||
module("awful.util")
|
||||
|
||||
function deprecate()
|
||||
print("W: awful: function is deprecated")
|
||||
print(debug.traceback())
|
||||
end
|
||||
|
||||
--- Strip alpha part of color.
|
||||
-- @param color The color.
|
||||
-- @return The color without alpha channel.
|
||||
function color_strip_alpha(color)
|
||||
if color:len() == 9 then
|
||||
color = color:sub(1, 7)
|
||||
end
|
||||
return color
|
||||
end
|
||||
|
||||
--- Make i cycle.
|
||||
-- @param t A length.
|
||||
-- @param i An absolute index to fit into #t.
|
||||
-- @return The object at new index.
|
||||
function cycle(t, i)
|
||||
while i > t do i = i - t end
|
||||
while i < 1 do i = i + t end
|
||||
return i
|
||||
end
|
||||
|
||||
--- Create a directory
|
||||
-- @param dir The directory.
|
||||
-- @return mkdir return code
|
||||
function mkdir(dir)
|
||||
return os.execute("mkdir -p " .. dir)
|
||||
end
|
||||
|
||||
--- Spawn a program.
|
||||
-- @param cmd The command.
|
||||
-- @param screen The screen where to spawn window.
|
||||
-- @return The awesome.spawn return value.
|
||||
function spawn(cmd, screen)
|
||||
if cmd and cmd ~= "" then
|
||||
return capi.awesome.spawn(cmd .. "&", screen or capi.mouse.screen)
|
||||
end
|
||||
end
|
||||
|
||||
-- Read a program output and returns its output as a string.
|
||||
-- @param cmd The command to run.
|
||||
-- @return A string with the program output.
|
||||
function pread(cmd)
|
||||
if cmd and cmd ~= "" then
|
||||
local f = io.popen(cmd, 'r')
|
||||
local s = f:read("*all")
|
||||
f:close()
|
||||
return s
|
||||
end
|
||||
end
|
||||
|
||||
--- Eval Lua code.
|
||||
-- @return The return value of Lua code.
|
||||
function eval(s)
|
||||
return assert(loadstring("return " .. s))()
|
||||
end
|
||||
|
||||
--- Escape a string from XML char.
|
||||
-- Useful to set raw text in textbox.
|
||||
-- @param text Text to escape.
|
||||
-- @return Escape text.
|
||||
function escape(text)
|
||||
if text then
|
||||
text = text:gsub("&", "&")
|
||||
text = text:gsub("<", "<")
|
||||
text = text:gsub(">", ">")
|
||||
text = text:gsub("'", "'")
|
||||
text = text:gsub("\"", """)
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
--- Unescape a string from entities.
|
||||
-- @param text Text to unescape.
|
||||
-- @return Unescaped text.
|
||||
function unescape(text)
|
||||
if text then
|
||||
text = text:gsub("&", "&")
|
||||
text = text:gsub("<", "<")
|
||||
text = text:gsub(">", ">")
|
||||
text = text:gsub("'", "'")
|
||||
text = text:gsub(""", "\"")
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -0,0 +1,255 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
-- @release @AWESOME_VERSION@
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment we need
|
||||
local ipairs = ipairs
|
||||
local pairs = pairs
|
||||
local capi =
|
||||
{
|
||||
screen = screen,
|
||||
client = client,
|
||||
button = button,
|
||||
widget = widget,
|
||||
mouse = mouse
|
||||
}
|
||||
local util = require("awful.util")
|
||||
local beautiful = require("awful.beautiful")
|
||||
|
||||
--- Widget module for awful
|
||||
module("awful.widget")
|
||||
|
||||
-- Various public structures
|
||||
taglist = {}
|
||||
taglist.label = {}
|
||||
tasklist = {}
|
||||
tasklist.label = {}
|
||||
|
||||
--- Return labels for a taglist widget with all tag from screen.
|
||||
-- It returns the tag name and set a special
|
||||
-- foreground and background color for selected tags.
|
||||
-- @param t The tag.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for selected tag.
|
||||
-- fg_focus The foreground color for selected tag.
|
||||
-- bg_urgent The background color for urgent tags.
|
||||
-- fg_urgent The foreground color for urgent tags.
|
||||
-- taglist_squares Optional: set "true" or nil to display the taglist squares.
|
||||
-- taglist_squares_sel Optional: an user provided image for selected squares.
|
||||
-- taglist_squares_unsel Optional: an user provided image for unselected squares.
|
||||
-- @return A string to print.
|
||||
function taglist.label.all(t, args)
|
||||
if not args then args = {} end
|
||||
local theme = beautiful.get()
|
||||
local fg_focus = args.fg_focus or theme.taglist_fg_focus or theme.fg_focus
|
||||
local bg_focus = args.bg_focus or theme.taglist_bg_focus or theme.bg_focus
|
||||
local fg_urgent = args.fg_urgent or theme.taglist_fg_urgent or theme.fg_urgent
|
||||
local bg_urgent = args.bg_urgent or theme.taglist_bg_urgent or theme.bg_urgent
|
||||
local taglist_squares = args.taglist_squares or theme.taglist_squares
|
||||
local taglist_squares_sel = args.squares_sel or theme.squares_sel
|
||||
local taglist_squares_unsel = args.squares_unsel or theme.squares_unsel
|
||||
local text
|
||||
local background = ""
|
||||
local sel = capi.client.focus
|
||||
local bg_color = nil
|
||||
local fg_color = nil
|
||||
if t.selected then
|
||||
bg_color = bg_focus
|
||||
fg_color = fg_focus
|
||||
end
|
||||
if sel and sel:tags()[t] then
|
||||
if not taglist_squares or taglist_squares == "true" then
|
||||
if taglist_squares_sel then
|
||||
background = "resize=\"true\" image=\"" .. taglist_squares_sel .. "\""
|
||||
else
|
||||
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarefw.png\""
|
||||
end
|
||||
end
|
||||
elseif bg_urgent or fg_urgent then
|
||||
for k, c in pairs(t:clients()) do
|
||||
if not taglist_squares or taglist_squares == "true" then
|
||||
if taglist_squares_unsel then
|
||||
background = "resize=\"true\" image=\"" .. taglist_squares_unsel .. "\""
|
||||
else
|
||||
background = "resize=\"true\" image=\"@AWESOME_ICON_PATH@/taglist/squarew.png\""
|
||||
end
|
||||
end
|
||||
if c.urgent then
|
||||
bg_color = bg_urgent
|
||||
fg_color = fg_urgent
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if bg_color and fg_color then
|
||||
text = "<bg "..background.." color='"..bg_color.."'/> <span color='"..util.color_strip_alpha(fg_color).."'>"..util.escape(t.name).."</span> "
|
||||
else
|
||||
text = " <bg "..background.." />"..util.escape(t.name).." "
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
--- Return labels for a taglist widget with all *non empty* tags from screen.
|
||||
-- It returns the tag name and set a special
|
||||
-- foreground and background color for selected tags.
|
||||
-- @param t The tag.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for selected tag.
|
||||
-- fg_focus The foreground color for selected tag.
|
||||
-- bg_urgent The background color for urgent tags.
|
||||
-- fg_urgent The foreground color for urgent tags.
|
||||
-- @return A string to print.
|
||||
function taglist.label.noempty(t, args)
|
||||
if #t:clients() > 0 or t.selected then
|
||||
if not args then args = {} end
|
||||
local theme = beautiful.get()
|
||||
local fg_focus = args.fg_focus or theme.taglist_fg_focus or theme.fg_focus
|
||||
local bg_focus = args.bg_focus or theme.taglist_bg_focus or theme.bg_focus
|
||||
local fg_urgent = args.fg_urgent or theme.taglist_fg_urgent or theme.fg_urgent
|
||||
local bg_urgent = args.bg_urgent or theme.taglist_bg_urgent or theme.bg_urgent
|
||||
local bg_color = nil
|
||||
local fg_color = nil
|
||||
local text
|
||||
|
||||
if t.selected then
|
||||
bg_color = bg_focus
|
||||
fg_color = fg_focus
|
||||
end
|
||||
if bg_urgent and fg_urgent then
|
||||
for k, c in pairs(t:clients()) do
|
||||
if c.urgent then
|
||||
bg_color = bg_urgent
|
||||
fg_color = fg_urgent
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if fg_color and bg_color then
|
||||
text = "<bg color='" .. bg_color .. "'/> <span color='" .. util.color_strip_alpha(fg_color) .. "'>" .. util.escape(t.name) .. "</span> "
|
||||
else
|
||||
text = " " .. util.escape(t.name) .. " "
|
||||
end
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
local function widget_tasklist_label_common(c, args)
|
||||
if not args then args = {} end
|
||||
local theme = beautiful.get()
|
||||
local fg_focus = args.fg_focus or theme.tasklist_fg_focus or theme.fg_focus
|
||||
local bg_focus = args.bg_focus or theme.tasklist_bg_focus or theme.bg_focus
|
||||
local fg_urgent = args.fg_urgent or theme.tasklist_fg_urgent or theme.fg_urgent
|
||||
local bg_urgent = args.bg_urgent or theme.tasklist_bg_urgent or theme.bg_urgent
|
||||
local text = ""
|
||||
local name
|
||||
if c.floating then
|
||||
text = "<bg image=\"@AWESOME_ICON_PATH@/tasklist/floatingw.png\" align=\"right\"/>"
|
||||
end
|
||||
if c.minimized then
|
||||
name = util.escape(c.icon_name) or ""
|
||||
else
|
||||
name = util.escape(c.name) or ""
|
||||
end
|
||||
if capi.client.focus == c then
|
||||
if bg_focus and fg_focus then
|
||||
text = text .. " <bg color='"..bg_focus.."'/><span color='"..util.color_strip_alpha(fg_focus).."'>"..name.."</span> "
|
||||
else
|
||||
text = text .. " "..name.." "
|
||||
end
|
||||
elseif c.urgent and bg_urgent and fg_urgent then
|
||||
text = text .. " <bg color='"..bg_urgent.."'/><span color='"..util.color_strip_alpha(fg_urgent).."'>"..name.."</span> "
|
||||
else
|
||||
text = text .. " "..name.." "
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
--- Return labels for a tasklist widget with clients from all tags and screen.
|
||||
-- It returns the client name and set a special
|
||||
-- foreground and background color for focused client.
|
||||
-- It also puts a special icon for floating windows.
|
||||
-- @param c The client.
|
||||
-- @param screen The screen we are drawing on.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for focused client.
|
||||
-- fg_focus The foreground color for focused client.
|
||||
-- bg_urgent The background color for urgent clients.
|
||||
-- fg_urgent The foreground color for urgent clients.
|
||||
-- @return A string to print.
|
||||
function tasklist.label.allscreen(c, screen, args)
|
||||
return widget_tasklist_label_common(c, args)
|
||||
end
|
||||
|
||||
--- Return labels for a tasklist widget with clients from all tags.
|
||||
-- It returns the client name and set a special
|
||||
-- foreground and background color for focused client.
|
||||
-- It also puts a special icon for floating windows.
|
||||
-- @param c The client.
|
||||
-- @param screen The screen we are drawing on.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for focused client.
|
||||
-- fg_focus The foreground color for focused client.
|
||||
-- bg_urgent The background color for urgent clients.
|
||||
-- fg_urgent The foreground color for urgent clients.
|
||||
-- @return A string to print.
|
||||
function tasklist.label.alltags(c, screen, args)
|
||||
-- Only print client on the same screen as this widget
|
||||
if c.screen ~= screen then return end
|
||||
return widget_tasklist_label_common(c, args)
|
||||
end
|
||||
|
||||
--- Return labels for a tasklist widget with clients from currently selected tags.
|
||||
-- It returns the client name and set a special
|
||||
-- foreground and background color for focused client.
|
||||
-- It also puts a special icon for floating windows.
|
||||
-- @param c The client.
|
||||
-- @param screen The screen we are drawing on.
|
||||
-- @param args The arguments table.
|
||||
-- bg_focus The background color for focused client.
|
||||
-- fg_focus The foreground color for focused client.
|
||||
-- bg_urgent The background color for urgent clients.
|
||||
-- fg_urgent The foreground color for urgent clients.
|
||||
-- @return A string to print.
|
||||
function tasklist.label.currenttags(c, screen, args)
|
||||
-- Only print client on the same screen as this widget
|
||||
if c.screen ~= screen then return end
|
||||
for k, t in ipairs(capi.screen[screen]:tags()) do
|
||||
if t.selected and c:tags()[t] then
|
||||
return widget_tasklist_label_common(c, args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Create a button widget. When clicked, the image is deplaced to make it like
|
||||
-- a real button.
|
||||
-- @param args Standard widget table arguments, plus image for the image path.
|
||||
-- @return A textbox widget configured as a button.
|
||||
function button(args)
|
||||
if not args then return end
|
||||
args.type = "textbox"
|
||||
local w = capi.widget(args)
|
||||
local img_release = "<bg image=\"" .. args.image .. "\" resize=\"true\"/>"
|
||||
local img_press = "<bg_margin top=\"2\" left=\"2\"/><bg image=\"" .. args.image .. "\" resize=\"true\"/>"
|
||||
w.text = img_release
|
||||
w:buttons({ capi.button({}, 1, function () w.text = img_press end, function () w.text = img_release end) })
|
||||
function w.mouse_leave(s) w.text = img_release end
|
||||
function w.mouse_enter(s) if capi.mouse.coords().buttons[1] then w.text = img_press end end
|
||||
return w
|
||||
end
|
||||
|
||||
--- Create a button widget which will launch a command.
|
||||
-- @param args Standard widget table arguments, plus image for the image path
|
||||
-- and command for the command to run on click.
|
||||
-- @return A launcher widget.
|
||||
function launcher(args)
|
||||
if not args.command then return end
|
||||
local w = button(args)
|
||||
local b = w:buttons()
|
||||
b[#b + 1] = capi.button({}, 1, nil, function () util.spawn(args.command) end)
|
||||
w:buttons(b)
|
||||
return w
|
||||
end
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80
|
|
@ -9,7 +9,7 @@
|
|||
local io = io
|
||||
local print = print
|
||||
local setmetatable = setmetatable
|
||||
local awful = require("awful")
|
||||
local util = require("awful.util")
|
||||
local package = package
|
||||
local capi =
|
||||
{
|
||||
|
@ -69,7 +69,7 @@ function init(path)
|
|||
if key then
|
||||
if key == "wallpaper_cmd" then
|
||||
for s = 1, capi.screen.count() do
|
||||
awful.spawn(value, s)
|
||||
util.spawn(value, s)
|
||||
end
|
||||
elseif key == "font" then
|
||||
capi.awesome.font(value)
|
||||
|
|
Loading…
Reference in New Issue