Merge pull request #2510 from Elv13/xmas_2k18_4
Add the popup widget take 2 (only relevant commits)
This commit is contained in:
commit
c87e7aad56
|
@ -1,7 +1,6 @@
|
|||
# The declarative layout system
|
||||
# The AwesomeWM widget system
|
||||
|
||||
The declarative layout system provides an alternative to the imperative system.
|
||||
It is inspired by the one used by Awesome 3.2-3.4 and the Qt QML style.
|
||||
This document explains how to define, place and manage widgets.
|
||||
|
||||
## The default widgets
|
||||
|
||||
|
@ -29,7 +28,127 @@ configurable rules.
|
|||
|
||||
@DOC_layout_WIDGET_LIST@
|
||||
|
||||
## Placing widgets
|
||||
### The different type of widget boxes (Wibox)
|
||||
|
||||
The Awesome API uses the word "wibox" (widget box) to describe an area of the
|
||||
screen filled with widgets. There are many subvariants of wiboxes with
|
||||
specialized roles such as widget bars or tooltips. All variants mostly share the
|
||||
same characteristics, but add some extra features to make those specialized
|
||||
widget boxes easier to work with.
|
||||
|
||||
@DOC_awful_popup_wiboxtypes_EXAMPLE@
|
||||
|
||||
The normal `wibox` is the base class for each of these types. It is extremely
|
||||
flexible and allows to place just about anything on the screen. However it
|
||||
requires a lot of repetitive boilerplate code to use directly. For example,
|
||||
the user needs to compute the optimal size by hand or use `awful.placement`.
|
||||
|
||||
The `awful.wibar` specialization allows to attach a `wibox` to a screen edge
|
||||
and prevents clients from using this area when tiled.
|
||||
|
||||
The `awful.popup` allows to easily place widgets on the screen. It automatically
|
||||
resizes itself to fit the optimal widget size. It also has helper properties
|
||||
and methods to make it easy to place it on the screen. It supports absolute
|
||||
positioning, relative positioning, and manual positioning.
|
||||
|
||||
The `awful.tooltip` is a very simple `wibox` that allows to display text next
|
||||
to an object such as the mouse.
|
||||
|
||||
Finally, the `awful.titlebar`, while not technically a real `wibox`, acts
|
||||
exactly the same way and allows to attach widgets on each side of clients.
|
||||
|
||||
## The different syntaxes to initiate widgets
|
||||
|
||||
Awesome provides 2 totally different API access styles to manage widgets. Both
|
||||
suit different use cases. Under the hood, both produce the
|
||||
exact same code. Consider the declarative API to be compiled into the
|
||||
imperative syntax when loaded. Also note that in contrast to technologies such
|
||||
as QML, it is interpreted only once and isn't automatically updated when
|
||||
values change.
|
||||
|
||||
The **imperative** widget initialization is similar to QtWidgets, GTK and Win32.
|
||||
You create the object, then set the property and add the widget as a child to
|
||||
another already declared widget. It is quite simple to use but very verbose
|
||||
and full of boilerplate code. The imperative API also offers properties both
|
||||
with accessors or directly. It is useful when creating highly dynamic layouts
|
||||
where widgets are added and removed over the course of their lifecycle.
|
||||
|
||||
The **declarative** syntax resembles HTML style code
|
||||
written in JSON or YAML. The widget instances are created automatically and
|
||||
the hierarchy is related to the table nesting (indentation). It is preferred
|
||||
when creating static layouts that won't change over the course of their
|
||||
lifecycle.
|
||||
|
||||
Here is the same code written in both the imperative and declarative style
|
||||
|
||||
**Imperative with accessors**
|
||||
|
||||
Code:
|
||||
|
||||
local bg = wibox.container.background()
|
||||
bg:set_bg("#ff0000")
|
||||
|
||||
local tb1 = wibox.widget.textbox()
|
||||
local tb2 = wibox.widget.textbox("bar")
|
||||
|
||||
tb1:set_text("foo")
|
||||
tb2:set_text("bar")
|
||||
|
||||
local l = wibox.layout.fixed.vertical()
|
||||
l:add(tb1)
|
||||
l:add(tb2)
|
||||
|
||||
bg:set_widget(l)
|
||||
|
||||
**Imperative with properties**
|
||||
|
||||
Code:
|
||||
|
||||
local bg = wibox.container.background()
|
||||
bg.bg = "#ff0000"
|
||||
|
||||
local tb1 = wibox.widget.textbox("foo")
|
||||
local tb2 = wibox.widget.textbox("bar")
|
||||
|
||||
tb1.text = "foo"
|
||||
tb2.text = "bar"
|
||||
|
||||
local l = wibox.layout.fixed.vertical()
|
||||
l:add(tb1)
|
||||
l:add(tb2)
|
||||
|
||||
bg.widget = l
|
||||
|
||||
**Declarative**
|
||||
|
||||
Code:
|
||||
|
||||
local bg = wibox.widget {
|
||||
{
|
||||
{
|
||||
text = "foo",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
{
|
||||
text = "bar",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical
|
||||
},
|
||||
bg = "#ff0000",
|
||||
widget = wibox.container.background
|
||||
}
|
||||
|
||||
|
||||
The Awesome documentation mostly uses the declarative style for consistency,
|
||||
but both are **always** available. Note that each style can be mixed with other
|
||||
styles, but this creates very confusing code and should be avoided.
|
||||
|
||||
## Creating and placing widgets using the declarative style
|
||||
|
||||
The examples below explain in detail how to use the declarative layout system.
|
||||
The imperative system is quite self explanatory and the respective widget API
|
||||
documentation should be enough for most.
|
||||
|
||||
### A simple layout
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ return
|
|||
ewmh = require("awful.ewmh");
|
||||
titlebar = require("awful.titlebar");
|
||||
rules = require("awful.rules");
|
||||
popup = require("awful.popup");
|
||||
spawn = spawn;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,467 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- An auto-resized, free floating or modal wibox built around a widget.
|
||||
--
|
||||
-- This type of widget box (wibox) is auto closed when being clicked on and is
|
||||
-- automatically resized to the size of its main widget.
|
||||
--
|
||||
-- Note that the widget itself should have a finite size. If something like a
|
||||
-- `wibox.layout.flex` is used, then the size would be unlimited and an error
|
||||
-- will be printed. The `wibox.layout.fixed`, `wibox.container.constraint`,
|
||||
-- `forced_width` and `forced_height` are recommended.
|
||||
--
|
||||
--@DOC_awful_popup_simple_EXAMPLE@
|
||||
--
|
||||
-- Here is an example of how to create an alt-tab like dialog by leveraging
|
||||
-- the `awful.widget.tasklist`.
|
||||
--
|
||||
--@DOC_awful_popup_alttab_EXAMPLE@
|
||||
--
|
||||
-- @author Emmanuel Lepage Vallee
|
||||
-- @copyright 2016 Emmanuel Lepage Vallee
|
||||
-- @classmod awful.popup
|
||||
---------------------------------------------------------------------------
|
||||
local wibox = require( "wibox" )
|
||||
local util = require( "awful.util" )
|
||||
local placement = require( "awful.placement" )
|
||||
local xresources= require("beautiful.xresources")
|
||||
local timer = require( "gears.timer" )
|
||||
local capi = {mouse = mouse}
|
||||
|
||||
|
||||
local module = {}
|
||||
|
||||
local main_widget = {}
|
||||
|
||||
-- Get the optimal direction for the wibox
|
||||
-- This (try to) avoid going offscreen
|
||||
local function set_position(self)
|
||||
-- First, if there is size to be applied, do it
|
||||
if self._private.next_width then
|
||||
self.width = self._private.next_width
|
||||
self._private.next_width = nil
|
||||
end
|
||||
|
||||
if self._private.next_height then
|
||||
self.height = self._private.next_height
|
||||
self._private.next_height = nil
|
||||
end
|
||||
|
||||
local pf = self._private.placement
|
||||
|
||||
if pf == false then return end
|
||||
|
||||
if pf then
|
||||
pf(self, {bounding_rect = self.screen.geometry})
|
||||
return
|
||||
end
|
||||
|
||||
local geo = self._private.widget_geo
|
||||
|
||||
if not geo then return end
|
||||
|
||||
local _, pos_name, anchor_name = placement.next_to(self, {
|
||||
preferred_positions = self._private.preferred_directions,
|
||||
geometry = geo,
|
||||
preferred_anchors = self._private.preferred_anchors,
|
||||
offset = self._private.offset or { x = 0, y = 0},
|
||||
})
|
||||
|
||||
if pos_name ~= self._private.current_position then
|
||||
local old = self._private.current_position
|
||||
self._private.current_position = pos_name
|
||||
self:emit_signal("property::current_position", pos_name, old)
|
||||
end
|
||||
|
||||
if anchor_name ~= self._private.current_anchor then
|
||||
local old = self._private.current_anchor
|
||||
self._private.current_anchor = anchor_name
|
||||
self:emit_signal("property::current_anchor", anchor_name, old)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the wibox size taking into consideration the limits
|
||||
local function apply_size(self, width, height, set_pos)
|
||||
local prev_geo = self:geometry()
|
||||
|
||||
width = math.max(self._private.minimum_width or 1, math.ceil(width or 1))
|
||||
height = math.max(self._private.minimum_height or 1, math.ceil(height or 1))
|
||||
|
||||
if self._private.maximum_width then
|
||||
width = math.min(self._private.maximum_width, width)
|
||||
end
|
||||
|
||||
if self._private.maximum_height then
|
||||
height = math.min(self._private.maximum_height, height)
|
||||
end
|
||||
|
||||
self._private.next_width, self._private.next_height = width, height
|
||||
|
||||
if set_pos or width ~= prev_geo.width or height ~= prev_geo.height then
|
||||
set_position(self)
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout this widget
|
||||
function main_widget:layout(context, width, height)
|
||||
if self._private.widget then
|
||||
local w, h = wibox.widget.base.fit_widget(
|
||||
self,
|
||||
context,
|
||||
self._private.widget,
|
||||
self._wb._private.maximum_width or 9999,
|
||||
self._wb._private.maximum_height or 9999
|
||||
)
|
||||
timer.delayed_call(function()
|
||||
apply_size(self._wb, w, h, true)
|
||||
end)
|
||||
return { wibox.widget.base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Set the widget that is drawn on top of the background
|
||||
function main_widget:set_widget(widget)
|
||||
if widget then
|
||||
wibox.widget.base.check_widget(widget)
|
||||
end
|
||||
self._private.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
function main_widget:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
function main_widget:get_children_by_id(name)
|
||||
return self._wb:get_children_by_id(name)
|
||||
end
|
||||
|
||||
local popup = {}
|
||||
|
||||
--- Set the preferred popup position relative to its parent.
|
||||
--
|
||||
-- This allows, for example, to have a submenu that goes on the right of the
|
||||
-- parent menu. If there is no space on the right, it tries on the left and so
|
||||
-- on.
|
||||
--
|
||||
-- Valid directions are:
|
||||
--
|
||||
-- * left
|
||||
-- * right
|
||||
-- * top
|
||||
-- * bottom
|
||||
--
|
||||
-- The basic use case for this method is to give it a parent wibox:
|
||||
--
|
||||
-- @DOC_awful_popup_position1_EXAMPLE@
|
||||
--
|
||||
-- As demonstrated by this second example, it is also possible to use a widget
|
||||
-- as a parent object:
|
||||
--
|
||||
-- @DOC_awful_popup_position2_EXAMPLE@
|
||||
--
|
||||
-- @property preferred_positions
|
||||
-- @tparam table|string preferred_positions A position name or an ordered
|
||||
-- table of positions
|
||||
-- @see awful.placement.next_to
|
||||
-- @see awful.popup.preferred_anchors
|
||||
|
||||
function popup:set_preferred_positions(pref_pos)
|
||||
self._private.preferred_directions = pref_pos
|
||||
set_position(self)
|
||||
end
|
||||
|
||||
--- Set the preferred popup anchors relative to the parent.
|
||||
--
|
||||
-- The possible values are:
|
||||
--
|
||||
-- * front
|
||||
-- * middle
|
||||
-- * back
|
||||
--
|
||||
-- For details information, see the `awful.placement.next_to` documentation.
|
||||
--
|
||||
-- In this example, it is possible to see the effect of having a fallback
|
||||
-- preferred anchors when the popup would otherwise not fit:
|
||||
--
|
||||
-- @DOC_awful_popup_anchors_EXAMPLE@
|
||||
--
|
||||
-- @property preferred_anchors
|
||||
-- @tparam table|string preferred_anchors Either a single anchor name or a table
|
||||
-- ordered by priority.
|
||||
-- @see awful.placement.next_to
|
||||
-- @see awful.popup.preferred_positions
|
||||
|
||||
function popup:set_preferred_anchors(pref_anchors)
|
||||
self._private.preferred_anchors = pref_anchors
|
||||
set_position(self)
|
||||
end
|
||||
|
||||
--- The current position relative to the parent object.
|
||||
--
|
||||
-- If there is a parent object (widget, wibox, wibar, client or the mouse), then
|
||||
-- this property returns the current position. This is determined using
|
||||
-- `preferred_positions`. It is usually the preferred position, but when there
|
||||
-- isn't enough space, it can also be one of the fallback.
|
||||
--
|
||||
-- @property current_position
|
||||
-- @tparam string current_position Either "left", "right", "top" or "bottom"
|
||||
|
||||
function popup:get_current_position()
|
||||
return self._private.current_position
|
||||
end
|
||||
|
||||
--- Get the current anchor relative to the parent object.
|
||||
--
|
||||
-- If there is a parent object (widget, wibox, wibar, client or the mouse), then
|
||||
-- this property returns the current anchor. The anchor is the "side" of the
|
||||
-- parent object on which the popup is based on. It will "grow" in the
|
||||
-- opposite direction from the anchor.
|
||||
--
|
||||
-- @property current_anchor
|
||||
-- @tparam string current_anchor Either "front", "middle", "back"
|
||||
|
||||
function popup:get_current_anchor()
|
||||
return self._private.current_anchor
|
||||
end
|
||||
|
||||
--- Move the wibox to a position relative to `geo`.
|
||||
-- This will try to avoid overlapping the source wibox and auto-detect the right
|
||||
-- direction to avoid going off-screen.
|
||||
--
|
||||
-- @param[opt=mouse] obj An object such as a wibox, client or a table entry
|
||||
-- returned by `wibox:find_widgets()`.
|
||||
-- @see awful.placement.next_to
|
||||
-- @see awful.popup.preferred_positions
|
||||
-- @see awful.popup.preferred_anchors
|
||||
-- @treturn table The new geometry
|
||||
function popup:move_next_to(obj)
|
||||
if self._private.is_relative == false then return end
|
||||
|
||||
self._private.widget_geo = obj
|
||||
|
||||
obj = obj or capi.mouse
|
||||
|
||||
if obj._apply_size_now then
|
||||
obj:_apply_size_now(false)
|
||||
end
|
||||
|
||||
self.visible = true
|
||||
|
||||
self:_apply_size_now(true)
|
||||
|
||||
self._private.widget_geo = nil
|
||||
end
|
||||
|
||||
--- Bind the popup to a widget button press.
|
||||
--
|
||||
-- @tparam widget widget The widget
|
||||
-- @tparam[opt=1] number button The button index
|
||||
function popup:bind_to_widget(widget, button)
|
||||
if not self._private.button_for_widget then
|
||||
self._private.button_for_widget = {}
|
||||
end
|
||||
|
||||
self._private.button_for_widget[widget] = button or 1
|
||||
widget:connect_signal("button::press", self._private.show_fct)
|
||||
end
|
||||
|
||||
--- Unbind the popup from a widget button.
|
||||
-- @tparam widget widget The widget
|
||||
function popup:unbind_to_widget(widget)
|
||||
widget:disconnect_signal("button::press", self._private.show_fct)
|
||||
end
|
||||
|
||||
--- Hide the popup when right clicked.
|
||||
--
|
||||
-- @property hide_on_right_click
|
||||
-- @tparam[opt=false] boolean hide_on_right_click
|
||||
|
||||
function popup:set_hide_on_right_click(value)
|
||||
self[value and "connect_signal" or "disconnect_signal"](
|
||||
self, "button::press", self._private.hide_fct
|
||||
)
|
||||
end
|
||||
|
||||
--- The popup minimum width.
|
||||
-- @property minimum_width
|
||||
-- @tparam[opt=1] number The minimum width
|
||||
|
||||
--- The popup minimum height.
|
||||
-- @property minimum_height
|
||||
-- @tparam[opt=1] number The minimum height
|
||||
|
||||
--- The popup minimum width.
|
||||
-- @property maxmimum_width
|
||||
-- @tparam[opt=1] number The maxmimum width
|
||||
|
||||
--- The popup maximum height.
|
||||
-- @property maximum_height
|
||||
-- @tparam[opt=1] number The maximum height
|
||||
|
||||
for _, orientation in ipairs {"_width", "_height"} do
|
||||
for _, limit in ipairs {"minimum", "maximum"} do
|
||||
popup["set_"..limit..orientation] = function(self, value)
|
||||
self._private[limit..orientation] = value
|
||||
self._private.container:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- The distance between the popup and its parent (if any).
|
||||
--
|
||||
-- Here is an example of 5 popups stacked one below the other with an y axis
|
||||
-- offset (spacing).
|
||||
--
|
||||
-- @DOC_awful_popup_position3_EXAMPLE@
|
||||
-- @property offset
|
||||
-- @tparam table|number offset An integer value or a `{x=, y=}` table.
|
||||
-- @tparam[opt=offset] number offset.x The horizontal distance.
|
||||
-- @tparam[opt=offset] number offset.y The vertical distance.
|
||||
|
||||
function popup:set_offset(offset)
|
||||
|
||||
if type(offset) == "number" then
|
||||
offset = {
|
||||
x = offset or 0,
|
||||
y = offset or 0,
|
||||
}
|
||||
end
|
||||
|
||||
local oldoff = self._private.offset or {x=0, y=0}
|
||||
|
||||
if oldoff.x == offset.x and oldoff.y == offset.y then return end
|
||||
|
||||
offset.x, offset.y = offset.x or oldoff.x or 0, offset.y or oldoff.y or 0
|
||||
|
||||
self._private.offset = offset
|
||||
|
||||
self:_apply_size_now(false)
|
||||
end
|
||||
|
||||
--- Set the placement function.
|
||||
-- @tparam[opt=next_to] function|string|boolean The placement function or name
|
||||
-- (or false to disable placement)
|
||||
-- @property placement
|
||||
-- @param function
|
||||
|
||||
function popup:set_placement(f)
|
||||
if type(f) == "string" then
|
||||
f = placement[f]
|
||||
end
|
||||
|
||||
self._private.placement = f
|
||||
self:_apply_size_now(false)
|
||||
end
|
||||
|
||||
-- For the tests and the race condition when 2 popups are placed next to each
|
||||
-- other.
|
||||
function popup:_apply_size_now(skip_set)
|
||||
if not self.widget then return end
|
||||
|
||||
local w, h = wibox.widget.base.fit_widget(
|
||||
self.widget,
|
||||
{dpi= self.screen.dpi or xresources.get_dpi()},
|
||||
self.widget,
|
||||
self._private.maximum_width or 9999,
|
||||
self._private.maximum_height or 9999
|
||||
)
|
||||
|
||||
-- It is important to do it for the obscure reason that calling `w:geometry()`
|
||||
-- is actually mutating the state due to quantum determinism thanks to XCB
|
||||
-- async nature... It is only true the very first time `w:geometry()` is
|
||||
-- called
|
||||
self.width = math.max(1, math.ceil(w or 1))
|
||||
self.height = math.max(1, math.ceil(h or 1))
|
||||
|
||||
apply_size(self, w, h, skip_set ~= false)
|
||||
end
|
||||
|
||||
function popup:set_widget(wid)
|
||||
self._private.widget = wid
|
||||
self._private.container:set_widget(wid)
|
||||
end
|
||||
|
||||
function popup:get_widget()
|
||||
return self._private.widget
|
||||
end
|
||||
|
||||
--- Create a new popup build around a passed in widget.
|
||||
-- @tparam[opt=nil] table args
|
||||
--@DOC_wibox_constructor_COMMON@
|
||||
-- @tparam function args.placement The `awful.placement` function
|
||||
-- @tparam string|table args.preferred_positions
|
||||
-- @tparam string|table args.preferred_anchors
|
||||
-- @tparam table|number args.offset The X and Y offset compared to the parent object
|
||||
-- @tparam boolean args.hide_on_right_click Whether or not to hide the popup on
|
||||
-- right clicks.
|
||||
-- @function awful.popup
|
||||
local function create_popup(_, args)
|
||||
assert(args)
|
||||
|
||||
-- Temporarily remove the widget
|
||||
local original_widget = args.widget
|
||||
args.widget = nil
|
||||
|
||||
assert(original_widget, "The `awful.popup` requires a `widget` constructor argument")
|
||||
|
||||
local child_widget = wibox.widget.base.make_widget_from_value(original_widget)
|
||||
|
||||
local ii = wibox.widget.base.make_widget(child_widget, "awful.popup", {
|
||||
enable_properties = true
|
||||
})
|
||||
|
||||
util.table.crush(ii, main_widget, true)
|
||||
|
||||
-- Create a wibox to host the widget
|
||||
local w = wibox(args or {})
|
||||
|
||||
rawset(w, "_private", {
|
||||
container = ii,
|
||||
preferred_directions = { "right", "left", "top", "bottom" },
|
||||
preferred_anchors = { "back", "front", "middle" },
|
||||
widget = child_widget
|
||||
})
|
||||
|
||||
util.table.crush(w, popup)
|
||||
|
||||
ii:set_widget(child_widget)
|
||||
|
||||
-- Create the signal handlers
|
||||
function w._private.show_fct(wdg, _, _, button, _, geo)
|
||||
if button == w._private.button_for_widget[wdg] then
|
||||
w:move_next_to(geo)
|
||||
end
|
||||
end
|
||||
function w._private.hide_fct()
|
||||
w.visible = false
|
||||
end
|
||||
|
||||
-- Restore
|
||||
args.widget = original_widget
|
||||
|
||||
-- Cross-link the wibox and widget
|
||||
ii._wb = w
|
||||
wibox.set_widget(w, ii)
|
||||
|
||||
--WARNING The order is important
|
||||
-- First, apply the limits to avoid a flicker with large width or height
|
||||
-- when set_position is called before the limits
|
||||
for _,v in ipairs{"minimum_width", "minimum_height", "maximum_height",
|
||||
"maximum_width", "offset", "placement","preferred_positions",
|
||||
"preferred_anchors", "hide_on_right_click"} do
|
||||
if args[v] ~= nil then
|
||||
w["set_"..v](w, args[v])
|
||||
end
|
||||
end
|
||||
|
||||
-- Default to visible
|
||||
if args.visible ~= false then
|
||||
w.visible = true
|
||||
end
|
||||
|
||||
return w
|
||||
end
|
||||
|
||||
--@DOC_wibox_COMMON@
|
||||
|
||||
return setmetatable(module, {__call = create_popup})
|
|
@ -0,0 +1,59 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { --DOC_HIDE --DOC_NO_USAGE
|
||||
popup = require("awful.popup"), --DOC_HIDE
|
||||
placement = require("awful.placement"), --DOC_HIDE
|
||||
widget = {clienticon =require("awful.widget.clienticon"), --DOC_HIDE
|
||||
tasklist = require("awful.widget.tasklist")} --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
local gears = { shape = require("gears.shape") } --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
local beautiful = require("beautiful") --DOC_HIDE
|
||||
|
||||
for _=1, 6 do --DOC_HIDE
|
||||
local c = client.gen_fake {x = 80, y = 55, width=75, height=50} --DOC_HIDE
|
||||
c.icon = beautiful.awesome_icon --DOC_HIDE
|
||||
c.minimized = true --DOC_HIDE
|
||||
end --DOC_HIDE
|
||||
|
||||
local tasklist_buttons = nil --DOC_HIDE
|
||||
|
||||
awful.popup {
|
||||
widget = awful.widget.tasklist {
|
||||
screen = screen[1],
|
||||
filter = awful.widget.tasklist.filter.allscreen,
|
||||
buttons = tasklist_buttons,
|
||||
style = {
|
||||
shape = gears.shape.rounded_rect,
|
||||
},
|
||||
layout = {
|
||||
spacing = 5,
|
||||
forced_num_rows = 2,
|
||||
layout = wibox.layout.grid.horizontal
|
||||
},
|
||||
|
||||
widget_template = {
|
||||
{
|
||||
{
|
||||
id = "clienticon",
|
||||
widget = awful.widget.clienticon,
|
||||
},
|
||||
margins = 4,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
id = "background_role",
|
||||
forced_width = 48,
|
||||
forced_height = 48,
|
||||
widget = wibox.container.background,
|
||||
create_callback = function(self, c, index, objects) --luacheck: no unused
|
||||
self:get_children_by_id("clienticon")[1].client = c
|
||||
end,
|
||||
},
|
||||
},
|
||||
border_color = "#777777",
|
||||
border_width = 2,
|
||||
ontop = true,
|
||||
placement = awful.placement.centered,
|
||||
shape = gears.shape.rounded_rect
|
||||
}
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,70 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { --DOC_HIDE --DOC_NO_USAGE
|
||||
popup = require("awful.popup"), --DOC_HIDE
|
||||
placement = require("awful.placement"), --DOC_HIDE
|
||||
widget = {clienticon =require("awful.widget.clienticon"), --DOC_HIDE
|
||||
tasklist = require("awful.widget.tasklist")} --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
screen[1]._resize {width = 320, height = 240} --DOC_HIDE
|
||||
screen._add_screen {x = 330, y = 0, width = 320, height = 240} --DOC_HIDE
|
||||
|
||||
local p = awful.popup { --DOC_HIDE
|
||||
widget = wibox.widget { --DOC_HIDE
|
||||
text = "Parent wibox", --DOC_HIDE
|
||||
forced_width = 100, --DOC_HIDE
|
||||
forced_height = 50, --DOC_HIDE
|
||||
widget = wibox.widget.textbox --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
border_color = "#777777", --DOC_HIDE
|
||||
border_width = 2, --DOC_HIDE
|
||||
ontop = true, --DOC_HIDE
|
||||
screen = screen[1], --DOC_HIDE
|
||||
placement = awful.placement.top, --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
p:_apply_size_now() --DOC_HIDE
|
||||
|
||||
local p2 = awful.popup {
|
||||
widget = wibox.widget {
|
||||
text = "A popup",
|
||||
forced_height = 100,
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
border_color = "#777777",
|
||||
border_width = 2,
|
||||
preferred_positions = "right",
|
||||
preferred_anchors = {"front", "back"},
|
||||
}
|
||||
p2:move_next_to(p) --DOC_HIDE
|
||||
|
||||
local p3 = awful.popup { --DOC_HIDE
|
||||
widget = wibox.widget { --DOC_HIDE
|
||||
text = "Parent wibox2", --DOC_HIDE
|
||||
forced_width = 100, --DOC_HIDE
|
||||
forced_height = 50, --DOC_HIDE
|
||||
widget = wibox.widget.textbox --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
border_color = "#777777", --DOC_HIDE
|
||||
border_width = 2, --DOC_HIDE
|
||||
ontop = true, --DOC_HIDE
|
||||
screen = screen[2], --DOC_HIDE
|
||||
placement = awful.placement.bottom, --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
p3:_apply_size_now() --DOC_HIDE
|
||||
|
||||
local p4 = awful.popup {
|
||||
widget = wibox.widget {
|
||||
text = "A popup2",
|
||||
forced_height = 100,
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
border_color = "#777777",
|
||||
border_width = 2,
|
||||
preferred_positions = "right",
|
||||
screen = screen[2], --DOC_HIDE
|
||||
preferred_anchors = {"front", "back"},
|
||||
}
|
||||
p4:move_next_to(p3) --DOC_HIDE
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,38 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { --DOC_HIDE --DOC_NO_USAGE
|
||||
popup = require("awful.popup"), --DOC_HIDE
|
||||
placement = require("awful.placement"), --DOC_HIDE
|
||||
widget = {clienticon =require("awful.widget.clienticon"), --DOC_HIDE
|
||||
tasklist = require("awful.widget.tasklist")} --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
local p = awful.popup { --DOC_HIDE
|
||||
widget = wibox.widget { --DOC_HIDE
|
||||
text = "Parent wibox", --DOC_HIDE
|
||||
forced_width = 100, --DOC_HIDE
|
||||
forced_height = 100, --DOC_HIDE
|
||||
widget = wibox.widget.textbox --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
border_color = "#777777", --DOC_HIDE
|
||||
border_width = 2, --DOC_HIDE
|
||||
ontop = true, --DOC_HIDE
|
||||
placement = awful.placement.centered, --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
p:_apply_size_now() --DOC_HIDE
|
||||
|
||||
for _, v in ipairs {"left", "right", "bottom", "top"} do
|
||||
local p2 = awful.popup {
|
||||
widget = wibox.widget {
|
||||
text = "On the "..v,
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
border_color = "#777777",
|
||||
border_width = 2,
|
||||
preferred_positions = v,
|
||||
ontop = true,
|
||||
}
|
||||
p2:move_next_to(p)
|
||||
end
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,61 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { --DOC_HIDE --DOC_NO_USAGE
|
||||
popup = require("awful.popup"), --DOC_HIDE
|
||||
placement = require("awful.placement"), --DOC_HIDE
|
||||
widget = {clienticon =require("awful.widget.clienticon"), --DOC_HIDE
|
||||
tasklist = require("awful.widget.tasklist")} --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
local gears = { shape = require("gears.shape"), timer=require("gears.timer") } --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
local beautiful = require("beautiful") --DOC_HIDE
|
||||
|
||||
local p = awful.popup { --DOC_HIDE
|
||||
widget = wibox.widget { --DOC_HIDE
|
||||
{ text = "Item", widget = wibox.widget.textbox }, --DOC_HIDE
|
||||
{ text = "Item", widget = wibox.widget.textbox }, --DOC_HIDE
|
||||
{ text = "Item", widget = wibox.widget.textbox }, --DOC_HIDE
|
||||
{ --DOC_HIDE
|
||||
{ --DOC_HIDE
|
||||
text = "Selected", --DOC_HIDE
|
||||
widget = wibox.widget.textbox --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
bg = beautiful.bg_highlight, --DOC_HIDE
|
||||
widget = wibox.container.background --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
{ text = "Item", widget = wibox.widget.textbox }, --DOC_HIDE
|
||||
{ text = "Item", widget = wibox.widget.textbox }, --DOC_HIDE
|
||||
forced_width = 100, --DOC_HIDE
|
||||
widget = wibox.layout.fixed.vertical --DOC_HIDE
|
||||
}, --DOC_HIDE
|
||||
border_color = "#ff0000", --DOC_HIDE
|
||||
border_width = 2, --DOC_HIDE
|
||||
placement = awful.placement.centered, --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
p:_apply_size_now() --DOC_HIDE
|
||||
awesome.emit_signal("refresh") --DOC_HIDE
|
||||
p._drawable._do_redraw() --DOC_HIDE
|
||||
|
||||
--DOC_HIDE Necessary as the widgets are drawn later
|
||||
gears.timer.delayed_call(function() --DOC_HIDE
|
||||
-- Get the 4th textbox --DOC_HIDE
|
||||
local list = p:find_widgets(30, 40) --DOC_HIDE
|
||||
mouse.coords {x= 120, y=125} --DOC_HIDE
|
||||
mouse.push_history() --DOC_HIDE
|
||||
local textboxinstance = list[#list] --DOC_HIDE
|
||||
|
||||
for _, v in ipairs {"left", "right"} do
|
||||
local p2 = awful.popup {
|
||||
widget = wibox.widget {
|
||||
text = "On the "..v,
|
||||
forced_height = 100,
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
border_color = "#0000ff",
|
||||
preferred_positions = v,
|
||||
border_width = 2,
|
||||
}
|
||||
p2:move_next_to(textboxinstance, v)
|
||||
end
|
||||
end) --DOC_HIDE
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,34 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { --DOC_HIDE --DOC_NO_USAGE
|
||||
popup = require("awful.popup"), --DOC_HIDE
|
||||
placement = require("awful.placement"), --DOC_HIDE
|
||||
widget = {clienticon =require("awful.widget.clienticon"), --DOC_HIDE
|
||||
tasklist = require("awful.widget.tasklist")} --DOC_HIDE
|
||||
} --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
local beautiful = require("beautiful") --DOC_HIDE
|
||||
|
||||
local previous = nil
|
||||
|
||||
for i=1, 5 do
|
||||
local p2 = awful.popup {
|
||||
widget = wibox.widget {
|
||||
text = "Hello world! "..i.." aaaa.",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
border_color = beautiful.border_color,
|
||||
preferred_positions = "bottom",
|
||||
border_width = 2,
|
||||
preferred_anchors = "back",
|
||||
placement = (not previous) and awful.placement.top or nil,
|
||||
offset = {
|
||||
y = 10,
|
||||
},
|
||||
}
|
||||
p2:_apply_size_now() --DOC_HIDE
|
||||
p2:move_next_to(previous)
|
||||
previous = p2
|
||||
previous:_apply_size_now() --DOC_HIDE
|
||||
end
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,42 @@
|
|||
--DOC_GEN_IMAGE --DOC_HIDE
|
||||
local awful = { placement = require("awful.placement"), --DOC_HIDE
|
||||
popup = require("awful.popup") } --DOC_HIDE --DOC_NO_USAGE
|
||||
local gears = { shape = require("gears.shape") } --DOC_HIDE
|
||||
local wibox = require("wibox") --DOC_HIDE
|
||||
|
||||
awful.popup {
|
||||
widget = {
|
||||
{
|
||||
{
|
||||
text = "foobar",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
{
|
||||
{
|
||||
text = "foobar",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
bg = "#ff00ff",
|
||||
clip = true,
|
||||
shape = gears.shape.rounded_bar,
|
||||
widget = wibox.widget.background
|
||||
},
|
||||
{
|
||||
value = 0.5,
|
||||
forced_height = 30,
|
||||
forced_width = 100,
|
||||
widget = wibox.widget.progressbar
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
margins = 10,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
border_color = "#00ff00",
|
||||
border_width = 5,
|
||||
placement = awful.placement.top_left,
|
||||
shape = gears.shape.rounded_rect,
|
||||
visible = true,
|
||||
}
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,247 @@
|
|||
--DOC_GEN_IMAGE
|
||||
--DOC_HIDE_ALL
|
||||
--DOC_NO_USAGE
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful") --DOC_HIDE
|
||||
|
||||
screen[1]._resize {width = 640, height = 480}
|
||||
|
||||
-- This example is used to show the various type of wibox awesome provides
|
||||
-- and mimic the default config look
|
||||
|
||||
local c = client.gen_fake {hide_first=true}
|
||||
|
||||
c:geometry {
|
||||
x = 50,
|
||||
y = 350,
|
||||
height = 100,
|
||||
width = 150,
|
||||
}
|
||||
c._old_geo = {c:geometry()}
|
||||
c:set_label("A client")
|
||||
|
||||
local wb = awful.wibar {
|
||||
position = "top",
|
||||
}
|
||||
|
||||
-- Create the same number of tags as the default config
|
||||
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, screen[1], awful.layout.layouts[1])
|
||||
|
||||
-- Only bother with widgets that are visible by default
|
||||
local mykeyboardlayout = awful.widget.keyboardlayout()
|
||||
local mytextclock = wibox.widget.textclock()
|
||||
local mylayoutbox = awful.widget.layoutbox(screen[1])
|
||||
local mytaglist = awful.widget.taglist(screen[1], awful.widget.taglist.filter.all, {})
|
||||
local mytasklist = awful.widget.tasklist(screen[1], awful.widget.tasklist.filter.currenttags, {})
|
||||
|
||||
wb:setup {
|
||||
layout = wibox.layout.align.horizontal,
|
||||
{ -- Left widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
awful.titlebar.widget.iconwidget(c), --looks close enough
|
||||
mytaglist,
|
||||
},
|
||||
mytasklist, -- Middle widget
|
||||
{ -- Right widgets
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
mykeyboardlayout,
|
||||
mytextclock,
|
||||
mylayoutbox,
|
||||
},
|
||||
}
|
||||
|
||||
-- The popup
|
||||
awful.popup {
|
||||
widget = wibox.widget {
|
||||
--TODO use the layoutlist for this example
|
||||
awful.widget.taglist {
|
||||
filter = awful.widget.taglist.filter.all,
|
||||
screen = 1,
|
||||
base_layout = wibox.widget {
|
||||
spacing = 5,
|
||||
forced_num_cols = 5,
|
||||
layout = wibox.layout.grid.vertical,
|
||||
},
|
||||
widget_template = {
|
||||
{
|
||||
--TODO use the layoutlist for this example
|
||||
-- {
|
||||
-- id = 'icon_role',
|
||||
-- forced_height = 22,
|
||||
-- forced_width = 22,
|
||||
-- widget = wibox.widget.imagebox,
|
||||
-- },
|
||||
{
|
||||
id = "text_role",
|
||||
forced_height = 22,
|
||||
forced_width = 22,
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
margins = 4,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
id = 'background_role',
|
||||
forced_width = 24,
|
||||
forced_height = 24,
|
||||
shape = gears.shape.rounded_rect,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
},
|
||||
margins = 4,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
border_color = beautiful.border_color,
|
||||
border_width = beautiful.border_width,
|
||||
placement = awful.placement.centered,
|
||||
ontop = true,
|
||||
shape = gears.shape.rounded_rect
|
||||
}
|
||||
|
||||
-- poor copy of awful.widget.calendar_widget until I fix its API to be less
|
||||
-- insane.
|
||||
local p10 = awful.popup {
|
||||
widget = {
|
||||
wibox.widget.calendar.month(os.date('*t')),
|
||||
top = 30,
|
||||
margins = 10,
|
||||
layout = wibox.container.margin
|
||||
},
|
||||
preferred_anchors = "middle",
|
||||
border_width = 2,
|
||||
border_color = beautiful.border_color,
|
||||
hide_on_right_click = true,
|
||||
placement = function(d) return awful.placement.top_right(d, {
|
||||
honor_workarea = true,
|
||||
}) end,
|
||||
shape = gears.shape.infobubble,
|
||||
}
|
||||
|
||||
awesome.emit_signal("refresh")
|
||||
p10:bind_to_widget(mytextclock)
|
||||
|
||||
-- The titlebar
|
||||
|
||||
local top_titlebar = awful.titlebar(c, {
|
||||
height = 20,
|
||||
bg_normal = "#ff0000",
|
||||
})
|
||||
|
||||
top_titlebar : setup {
|
||||
{ -- Left
|
||||
awful.titlebar.widget.iconwidget(c),
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
},
|
||||
{ -- Middle
|
||||
{ -- Title
|
||||
align = "center",
|
||||
widget = awful.titlebar.widget.titlewidget(c)
|
||||
},
|
||||
layout = wibox.layout.flex.horizontal
|
||||
},
|
||||
{ -- Right
|
||||
awful.titlebar.widget.floatingbutton (c),
|
||||
awful.titlebar.widget.maximizedbutton(c),
|
||||
awful.titlebar.widget.stickybutton (c),
|
||||
awful.titlebar.widget.ontopbutton (c),
|
||||
awful.titlebar.widget.closebutton (c),
|
||||
layout = wibox.layout.fixed.horizontal()
|
||||
},
|
||||
layout = wibox.layout.align.horizontal
|
||||
}
|
||||
|
||||
-- Normal wiboxes
|
||||
|
||||
wibox {
|
||||
width = 50,
|
||||
height = 50,
|
||||
shape = gears.shape.octogon,
|
||||
color = "#0000ff",
|
||||
x = 570,
|
||||
y = 410,
|
||||
border_width = 2,
|
||||
border_color = beautiful.border_color,
|
||||
}
|
||||
|
||||
-- The tooltip
|
||||
|
||||
mouse.coords{x=50, y= 100}
|
||||
mouse.push_history()
|
||||
|
||||
local tt = awful.tooltip {
|
||||
text = "A tooltip!",
|
||||
visible = true,
|
||||
}
|
||||
tt.bg = beautiful.bg_normal
|
||||
|
||||
-- Extra information overlay
|
||||
|
||||
local overlay_w = wibox {
|
||||
bg = "#00000000",
|
||||
visible = true,
|
||||
ontop = true,
|
||||
}
|
||||
|
||||
awful.placement.maximize(overlay_w)
|
||||
|
||||
local canvas = wibox.layout.manual()
|
||||
canvas.forced_height = 480
|
||||
canvas.forced_width = 640
|
||||
overlay_w:set_widget(canvas)
|
||||
|
||||
local function create_info(text, x, y, width, height)
|
||||
canvas:add_at(wibox.widget {
|
||||
{
|
||||
{
|
||||
text = text,
|
||||
align = "center",
|
||||
ellipsize = "none",
|
||||
widget = wibox.widget.textbox
|
||||
},
|
||||
margins = 10,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
forced_width = width,
|
||||
forced_height = height,
|
||||
shape = gears.shape.rectangle,
|
||||
shape_border_width = 1,
|
||||
shape_border_color = beautiful.border_color,
|
||||
bg = "#ffff0055",
|
||||
widget = wibox.container.background
|
||||
}, {x = x, y = y})
|
||||
end
|
||||
|
||||
local function create_line(x1, y1, x2, y2)
|
||||
return canvas:add_at(wibox.widget {
|
||||
fit = function()
|
||||
return x2-x1+6, y2-y1+6
|
||||
end,
|
||||
draw = function(_, _, cr)
|
||||
cr:set_source_rgb(0,0,0)
|
||||
cr:set_line_width(1)
|
||||
cr:arc(1.5, 1.5, 1.5, 0, math.pi*2)
|
||||
cr:arc(x2-x1+1.5, y2-y1+1.5, 1.5, 0, math.pi*2)
|
||||
cr:fill()
|
||||
cr:move_to(1.5,1.5)
|
||||
cr:line_to(x2-x1+1.5, y2-y1+1.5)
|
||||
cr:stroke()
|
||||
end,
|
||||
layout = wibox.widget.base.make_widget,
|
||||
}, {x=x1, y=y1})
|
||||
end
|
||||
|
||||
create_info("awful.wibar", 200, 50, 100, 30)
|
||||
create_info("awful.titlebar", 250, 350, 100, 30)
|
||||
create_info("awful.tooltip", 30, 130, 100, 30)
|
||||
create_info("awful.popup", 450, 240, 100, 30)
|
||||
create_info("Standard `wibox1`", 420, 420, 130, 30)
|
||||
|
||||
create_line(250, 10, 250, 55)
|
||||
create_line(75, 100, 75, 135)
|
||||
create_line(545, 432, 575, 432)
|
||||
create_line(500, 165, 500, 245)
|
||||
create_line(390, 250, 450, 250)
|
||||
create_line(190, 365, 255, 365)
|
||||
|
||||
--DOC_HIDE vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
Loading…
Reference in New Issue