Skip to content

Commit

Permalink
Added quake style dropdown terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
LycanDarko666 committed Sep 14, 2023
1 parent e7e2354 commit 1ebdfca
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 94 deletions.
3 changes: 3 additions & 0 deletions rabbithole/components/keys/global.lua
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ return setmetatable({}, {
}
end,
{ description = "lua execute prompt", group = "awesome" }),

-- quake style dropdown terminal bound to mod4 + \
awful.key({ modkey }, "\\", function () awful.screen.focused().quake:toggle() end, {description = "dropdown application", group = "launcher"}),

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
-- Resize
Expand Down
139 changes: 45 additions & 94 deletions rabbithole/components/widgets/common/elements-popup.lua
Original file line number Diff line number Diff line change
@@ -1,110 +1,61 @@
local Widget = require("elements-base-ui") -- Make sure the path is correct0
-- This is a popup container that holds a widget. This is going to be used as
-- the container for the dropdown terminal, dropdown file manager, and quick notes.
-- The popup container is a wibox that drops down from the top of the screen.
-- It is used to hold widgets that are toggled on and off.

local gears = require("gears")
local wibox = require("wibox")
local awful = require("awful")
local Animations = require("rabbithole.components.widgets.themeEngines.elements-animations") -- Make sure the path is correct

--[[ Usage:
local my_popup = Popup({
width = 200,
height = 100,
bg = "#ffffff",
border_color = "#000000",
border_width = 1,
position = "bottom_right",
animation = "slide_in",
animation_duration = 250
})
-- Add content to the popup
my_popup.popup:setup {
{
{
text = "This is a popup!",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
margins = 10,
widget = wibox.container.margin
},
widget = wibox.container.background
}
local wibox = require("wibox")
local dpi = require("beautiful").xresources.apply_dpi

-- Show the popup
my_popup:show()

-- You can use a timer or any event to hide the popup after
local DropdownContainer = {}
DropdownContainer.__index = DropdownContainer

]]

local Popup = class(Widget)
function DropdownContainer:new(program, args)
setmetatable({}, self)

function Popup:init(args)
args = args or {}
self.width = args.width or 200
self.height = args.height or 100
self.bg = args.bg or "#ffffff"
self.border_color = args.border_color or "#000000"
self.border_width = args.border_width or 1
self.position = args.position or "bottom_right"
self.animation = args.animation or "slide_in"
self.animation_duration = args.animation_duration or 250
self.program = program
self.args = args
self.visible = false
self:setup()

-- Create a wibox for the popup
self.popup = wibox({
ontop = true,
visible = false,
width = self.width,
height = self.height,
bg = self.bg,
border_color = self.border_color,
border_width = self.border_width,
shape = gears.shape.rounded_rect
})

-- Set the position of the popup
self:set_position(self.position)

-- Initialize the animations class
self.animations = Animations()
return self
end

function Popup:set_position(position)
local s = awful.screen.focused()
local x, y

if position == "bottom_right" then
x = s.geometry.x + s.geometry.width - self.width
y = s.geometry.y + s.geometry.height - self.height
-- Add other positions here
else
x = s.geometry.x + s.geometry.width / 2 - self.width / 2
y = s.geometry.y + s.geometry.height / 2 - self.height / 2
end

self.popup.x = x
self.popup.y = y
-- Popup dropdown container wrapper
function DropdownContainer:create()
self.popup = awful.popup {
widget = {
{
{
self.program, -- Replace with your terminal emulator's command
widget = wibox.widget.textbox
},
margins = dpi(4),
widget = wibox.container.margin
},
widget = wibox.container.background
},
visible = false,
ontop = true,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
}
end

function Popup:show()
if not self.popup.visible then
self.popup.visible = true
if self.animation == "slide_in" then
self.animations:slideIn(self.popup, self.animation_duration, self.position)
end
end
-- toggle visibility
function DropdownContainer:toggle()
self.visible = not self.visible
self.popup.visible = self.visible
end

function Popup:hide()
if self.popup.visible then
if self.animation == "slide_in" then
self.animations:slideOut(self.popup, self.animation_duration, self.position, function()
self.popup.visible = false
end)
else
self.popup.visible = false
end
end
-- initialist the popup
function DropdownContainer:setup()
self:create()
self:toggle()
end

return DropdownContainer
168 changes: 168 additions & 0 deletions rabbithole/services/quake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
--[[
Licensed under GNU General Public License v2
* (c) 2016, Luca CPZ
* (c) 2015, unknown
--]]

local awful = require("awful")
local capi = { client = client }
local math = math
local string = string
local pairs = pairs
local screen = screen
local setmetatable = setmetatable

-- Quake-like Dropdown application spawn
local quake = {}

-- If you have a rule like "awful.client.setslave" for your terminals,
-- ensure you use an exception for QuakeDD. Otherwise, you may
-- run into problems with focus.

function quake:display()
if self.followtag then self.screen = awful.screen.focused() end

-- First, we locate the client
local client = nil
local i = 0
for c in awful.client.iterate(function (c)
-- c.name may be changed!
return c.instance == self.name
end)
do
i = i + 1
if i == 1 then
client = c
else
-- Additional matching clients, let's remove the sticky bit
-- which may persist between awesome restarts. We don't close
-- them as they may be valuable. They will just turn into
-- normal clients.
c.sticky = false
c.ontop = false
c.above = false
end
end

if not client and not self.visible then return end

if not client then
-- The client does not exist, we spawn it
cmd = string.format("%s %s %s", self.app,
string.format(self.argname, self.name), self.extra)
awful.spawn(cmd, { tag = self.screen.selected_tag })
return
end

-- Set geometry
client.floating = true
client.border_width = self.border
client.size_hints_honor = false
client:geometry(self.geometry[self.screen.index] or self:compute_size())

-- Set not sticky and on top
client.sticky = false
client.ontop = true
client.above = true
client.skip_taskbar = true

-- Additional user settings
if self.settings then self.settings(client) end

-- Toggle display
if self.visible then
client.hidden = false
client:raise()
self.last_tag = self.screen.selected_tag
client:tags({self.screen.selected_tag})
capi.client.focus = client
else
client.hidden = true
local ctags = client:tags()
for i, t in pairs(ctags) do
ctags[i] = nil
end
client:tags(ctags)
end

return client
end

function quake:compute_size()
-- skip if we already have a geometry for this screen
if not self.geometry[self.screen.index] then
local geom
if not self.overlap then
geom = screen[self.screen.index].workarea
else
geom = screen[self.screen.index].geometry
end
local width, height = self.width, self.height
if width <= 1 then width = math.floor(geom.width * width) - 2 * self.border end
if height <= 1 then height = math.floor(geom.height * height) end
local x, y
if self.horiz == "left" then x = geom.x
elseif self.horiz == "right" then x = geom.width + geom.x - width
else x = geom.x + (geom.width - width)/2 end
if self.vert == "top" then y = geom.y
elseif self.vert == "bottom" then y = geom.height + geom.y - height
else y = geom.y + (geom.height - height)/2 end
self.geometry[self.screen.index] = { x = x, y = y, width = width, height = height }
end
return self.geometry[self.screen.index]
end

function quake:new(config)
local conf = config or {}

conf.app = conf.app or "xterm" -- application to spawn
conf.name = conf.name or "QuakeDD" -- window name
conf.argname = conf.argname or "-name %s" -- how to specify window name
conf.extra = conf.extra or "" -- extra arguments
conf.border = conf.border or 1 -- client border width
conf.visible = conf.visible or false -- initially not visible
conf.followtag = conf.followtag or false -- spawn on currently focused screen
conf.overlap = conf.overlap or false -- overlap wibox
conf.screen = conf.screen or awful.screen.focused()
conf.settings = conf.settings

-- If width or height <= 1 this is a proportion of the workspace
conf.height = conf.height or 0.25 -- height
conf.width = conf.width or 1 -- width
conf.vert = conf.vert or "top" -- top, bottom or center
conf.horiz = conf.horiz or "left" -- left, right or center
conf.geometry = {} -- internal use

local dropdown = setmetatable(conf, { __index = quake })

capi.client.connect_signal("manage", function(c)
if c.instance == dropdown.name and c.screen == dropdown.screen then
dropdown:display()
end
end)
capi.client.connect_signal("unmanage", function(c)
if c.instance == dropdown.name and c.screen == dropdown.screen then
dropdown.visible = false
end
end)

return dropdown
end

function quake:toggle()
if self.followtag then self.screen = awful.screen.focused() end
local current_tag = self.screen.selected_tag
if current_tag and self.last_tag ~= current_tag and self.visible then
local c=self:display()
if c then
c:move_to_tag(current_tag)
end
else
self.visible = not self.visible
self:display()
end
end

return setmetatable(quake, { __call = function(_, ...) return quake:new(...) end })
5 changes: 5 additions & 0 deletions rabbithole/ui/default/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local awful = require("awful")
local beautiful = require("beautiful")
local bling = require("sub.bling")
local quake = require("rabbithole.services.quake")


local UserInterface = {}
UserInterface.__index = UserInterface
Expand All @@ -23,6 +25,9 @@ function UserInterface.new(
end
rabbithole__ui__default__center(s)

-- create dropdown terminal box for each screen
s.quake = quake({ app = "alacritty",argname = "--title %s",extra = "--class QuakeDD -e tmux", visible = true, height = 0.9, screen = s })

-- set dpi of screens
local resolution = s.geometry.width * s.geometry.height
local dpi
Expand Down

0 comments on commit 1ebdfca

Please sign in to comment.