2022-08-31 12:20:58 +00:00
-- This file is part of Reno desktop.
--
-- Reno desktop is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
--
-- Reno desktop is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
2022-08-11 19:34:25 +00:00
local gears = require ( " gears " )
2022-08-21 12:28:28 +00:00
local awmtk2 = require ( " awmtk2 " )
2022-08-11 19:34:25 +00:00
local wibox = require ( " wibox " )
local awful = require ( " awful " )
local beautiful = require ( " beautiful " )
2022-08-21 12:28:28 +00:00
local builder = require ( " builder " )
2022-08-25 15:27:31 +00:00
local json = require ( " dkjson " )
2022-08-11 19:34:25 +00:00
2022-08-21 12:28:28 +00:00
local function read_file ( fname )
local fhandler = io.open ( fname , " r " )
if fhandler then
local data = fhandler : read ( " *a " )
fhandler : close ( )
return data
end
end
2022-08-23 13:03:15 +00:00
2022-08-21 12:28:28 +00:00
-- {{{ Placeholder Icons
client.connect_signal ( " request::titlebars " , function ( c )
if ( not c.icon ) and beautiful.icon_default then
2022-08-23 13:03:15 +00:00
c.icon = beautiful.icon_default . _native
2022-08-21 12:28:28 +00:00
end
end )
-- }}}
2022-08-11 19:34:25 +00:00
2022-08-25 15:27:31 +00:00
do -- {{{ Global widgets
local config_file = io.open ( root_path .. " /themes/ " .. global.theme .. " /config/global.json " , " r " )
local config
if config_file then
config = config_file : read ( " *a " )
config_file : close ( )
else
config = " [] "
end
for k , v in pairs ( json.decode ( config ) or { } ) do
require ( k ) ( v )
end
end -- }}}
2022-09-04 10:49:18 +00:00
do --{{{ Screen
local wibar_config = { }
2022-09-06 22:40:51 +00:00
local style = awmtk2.create_style ( " wibar " , awmtk2.generic . composite_widget , { } )
2023-01-19 13:42:20 +00:00
for _ , v in pairs ( { " wibar_top " , " wibar_bottom " , " wibar_left " , " wibar_right " } ) do
style [ v ] = awmtk2.create_delta ( v , { } ,
( beautiful.widgets and beautiful.widgets . wibar ) or { } ,
2022-09-04 10:49:18 +00:00
style.wibar )
wibar_config [ v ] = read_file ( root_path .. " /themes/ " .. global.theme .. " /config/ " .. v .. " .json " )
end
local templates = awmtk2.create_template_lib ( " wibar " , awmtk2.templates , { } )
local t = awmtk2.build_templates ( templates , style )
awful.screen . connect_for_each_screen ( function ( s )
2023-01-19 13:42:20 +00:00
for _ , v in pairs ( { " wibar_top " , " wibar_bottom " , " wibar_left " , " wibar_right " } ) do
2022-09-04 10:49:18 +00:00
local contents = { widget = wibox.container . background }
if wibar_config [ v ] then
contents = builder ( wibar_config [ v ] , {
client = c ,
style = style [ v ] ,
buttons = buttons ,
2023-01-19 13:42:20 +00:00
screen = s
2022-09-04 10:49:18 +00:00
} )
s [ v ] = awful.wibar ( {
-- There really isn't a better way to do this. I wish there was.
position = v : gsub ( " wibar_ " , " " ) ,
screen = s ,
visible = true ,
stretch = style [ v ] . stretch ,
ontop = style [ v ] . ontop ,
width = style [ v ] . width ,
height = style [ v ] . height ,
border_width = style [ v ] . border_width ,
border_color = style [ v ] . border_color ,
opacity = style [ v ] . opacity or 1 ,
shape = style [ v ] . shape ,
2022-09-07 17:43:25 +00:00
bg = style [ v ] . bg_normal ,
bgimage = style [ v ] . bgimage_normal ,
2022-09-04 10:49:18 +00:00
fg = style [ v ] . fg ,
input_passthrough = style [ v ] . input_passthrough
} )
s [ v ] : setup ( t.wibar ( contents ) )
end
end
end )
end -- }}}
2022-08-11 19:34:25 +00:00
2022-08-21 12:28:28 +00:00
do -- {{{ Titlebars
local titlebar_config = { }
2022-09-06 22:40:51 +00:00
local style = awmtk2.create_style ( " titlebar " , awmtk2.generic . composite_widget , { } )
2023-01-19 13:42:20 +00:00
for _ , v in pairs ( { " titlebar_top " , " titlebar_left " , " titlebar_right " , " titlebar_bottom " } ) do
2022-08-21 12:28:28 +00:00
-- Create styles for each titlebar
2023-01-19 13:42:20 +00:00
style [ v ] = awmtk2.create_delta ( v , { } ,
( beautiful.widgets and beautiful.widgets . titlebar ) or { } ,
2022-08-21 12:28:28 +00:00
style.titlebar )
-- Load in json layouts for titlebars
titlebar_config [ v ] = read_file ( root_path .. " /themes/ " .. global.theme .. " /config/ " .. v .. " .json " )
end
2022-08-11 19:34:25 +00:00
local templates = awmtk2.create_template_lib ( " titlebar " , awmtk2.templates , { } )
local t = awmtk2.build_templates ( templates , style )
2022-08-21 12:28:28 +00:00
-- Add titlebars to normal windows
2022-08-11 19:34:25 +00:00
table.insert ( awful.rules . rules ,
{ rule_any = { type = { " normal " , " dialog " }
} , properties = { titlebars_enabled = true }
}
)
2022-09-08 10:56:04 +00:00
2022-12-10 22:28:22 +00:00
local window_shape_hide = function ( cr , width , height )
return gears.shape . partially_rounded_rect ( cr , width , height ,
false , false , false , false , 0 )
end
local window_shape = beautiful.window_shape or function ( cr , width , height )
return gears.shape . partially_rounded_rect ( cr , width , height ,
true , true , false , false , beautiful.window_rounding )
end
2022-09-08 10:56:04 +00:00
client.connect_signal ( " manage " , function ( c )
2022-12-10 22:28:22 +00:00
c.shape = window_shape
end )
local titlebars_on = true
awesome.connect_signal ( " titlebar::toggle " , function ( )
titlebars_on = not titlebars_on
for _ , c in ipairs ( client.get ( ) ) do
if titlebars_on then
for _ , pos in ipairs ( { " top " , " bottom " , " left " , " right " } ) do
awful.titlebar . show ( c , pos )
end
c.shape = window_shape
c : emit_signal ( " titlebar::perform_action " , function ( titlebar )
titlebar.widget . visible = true
end )
else
for _ , pos in ipairs ( { " top " , " bottom " , " left " , " right " } ) do
awful.titlebar . hide ( c , pos )
end
c.shape = window_shape_hide
c : emit_signal ( " titlebar::perform_action " , function ( titlebar )
titlebar.widget . visible = false
end )
end
2022-09-08 10:56:04 +00:00
end
end )
2022-12-10 22:28:22 +00:00
-- Second manage call to create hidden titlebars
client.connect_signal ( " manage " , function ( c )
-- Drag and resize buttons
2022-08-11 19:34:25 +00:00
local buttons = gears.table . join (
awful.button ( { } , 1 , function ( )
c : emit_signal ( " request::activate " , " titlebar " , { raise = true } )
awful.mouse . client.move ( c )
end ) ,
awful.button ( { } , 3 , function ( )
c : emit_signal ( " request::activate " , " titlebar " , { raise = true } )
awful.mouse . client.resize ( c )
end )
)
2022-12-10 22:28:22 +00:00
-- Building the titlebars
2022-08-21 12:28:28 +00:00
for k , v in pairs ( { " titlebar_top " , " titlebar_bottom " , " titlebar_left " , " titlebar_right " } ) do
2022-12-10 22:28:22 +00:00
-- Build content of the titlebar
local contents = { widget = wibox.widget . textbox , text = " " }
2022-08-21 12:28:28 +00:00
if titlebar_config [ v ] then
contents = builder ( titlebar_config [ v ] , {
client = c ,
2022-08-23 13:03:15 +00:00
screen = c.screen ,
2022-08-21 12:28:28 +00:00
style = style [ v ] ,
buttons = buttons
} )
end
2022-12-10 22:28:22 +00:00
-- Create the base
2022-09-08 17:52:03 +00:00
local titlebar = awful.titlebar ( c , {
2022-08-21 12:28:28 +00:00
size = style [ v ] . size or 0 ,
position = v : gsub ( " titlebar_ " , " " ) ,
bg_normal = style [ v ] . bg_normal ,
bg_focus = style [ v ] . bg_focus ,
bgimage_normal = style [ v ] . bgimage_normal ,
bgimage_focus = style [ v ] . bgimage_focus ,
fg_normal = style [ v ] . fg_normal ,
fg_focus = style [ v ] . fg_focus ,
font = style [ v ] . font
2022-09-08 17:52:03 +00:00
} )
2022-12-10 22:28:22 +00:00
-- Compile and build titlebar
titlebar : setup ( t.titlebar ( {
contents ,
widget = wibox.container . background
} ) )
-- Since new clients will be placed without titlebars, we need to apply placement rules again
2022-09-04 10:49:18 +00:00
awful.rules . rules [ 1 ] . properties.placement ( c )
2022-12-10 22:28:22 +00:00
-- Callbacks for focus/unfocus of titlebars
2022-09-08 17:52:03 +00:00
if style [ v ] . onfocus then
c : connect_signal ( " focus " , function ( )
style [ v ] . onfocus ( titlebar )
end )
end
if style [ v ] . onunfocus then
c : connect_signal ( " unfocus " , function ( )
style [ v ] . onunfocus ( titlebar )
end )
end
2022-12-10 22:28:22 +00:00
-- Activate focus callback if our client is focused
if ( c == client.focus ) and ( style [ v ] . onfocus ) then
style [ v ] . onfocus ( titlebar )
end
-- Add a titlebar toggle signal
c : connect_signal ( " titlebar::toggle " , function ( c )
titlebar.widget . visible = not titlebar.widget . visible
if titlebar.widget . visible then
awful.titlebar . show ( c , v : gsub ( " titlebar_ " , " " ) )
c.shape = window_shape
else
awful.titlebar . hide ( c , v : gsub ( " titlebar_ " , " " ) )
c.shape = window_shape_hide
end
2022-09-16 18:42:50 +00:00
end )
2022-12-10 22:28:22 +00:00
c : connect_signal ( " titlebar::perform_action " , function ( c , f )
f ( titlebar )
2022-09-16 18:42:50 +00:00
end )
2022-12-10 22:28:22 +00:00
-- Add rules for hiding titlebars on creation
if ( not titlebars_on ) or
( c.titlebars_enabled == false ) or
( c.requests_no_titlebar == true ) then
titlebar.widget . visible = false
c.shape = window_shape_hide
awful.titlebar . hide ( c , v : gsub ( " titlebar_ " , " " ) )
end
2022-08-21 12:28:28 +00:00
end
2022-08-11 19:34:25 +00:00
end )
2022-08-21 12:28:28 +00:00
end --}}}
2023-03-11 09:09:55 +00:00
-- Find a client to focus on when switching tags
2023-03-10 23:35:55 +00:00
for s in screen do
for _ , t in pairs ( awful.tag . gettags ( s ) ) do
t : connect_signal ( " property::selected " , function ( t )
if not client.focus then
local c = t : clients ( ) [ 1 ]
if c then
client.focus = c
end
end
end )
end
end
2023-03-11 09:09:55 +00:00
-- Focus on the previous client once the newer client is closed
client.connect_signal ( " unmanage " , function ( c )
local focused_clients = screen.primary . clients
local prev
for _ , v in pairs ( focused_clients ) do
if v == c then break end
prev = v
end
client.focus = prev
end )