transient.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. -- @author cedlemo
  2. -- Modifications based on original work from Uli Schlachter
  3. -- @copyright 2010 Uli Schlachter
  4. local capi = {
  5. drawin = drawin,
  6. root = root,
  7. awesome = awesome,
  8. screen = screen,
  9. mouse = mouse
  10. }
  11. local setmetatable = setmetatable
  12. local pairs = pairs
  13. local type = type
  14. local table = table
  15. local string_format = string.format
  16. local color = require("gears.color")
  17. local object = require("gears.object")
  18. local beautiful = require("beautiful")
  19. local surface = require("gears.surface")
  20. local cairo = require("lgi").cairo
  21. ---Wibox with timeout
  22. --@module blingbling.transient
  23. --- This provides widget box windows. Every transient can also be used as if it were
  24. -- a drawin. All drawin functions and properties are also available on transientes!
  25. -- transient
  26. local transient = { mt = {} }
  27. transient.layout = require("wibox.layout")
  28. transient.widget = require("wibox.widget")
  29. transient.drawable = require("wibox.drawable")
  30. --- Set the widget that the transient displays
  31. function transient:set_widget(widget)
  32. self._drawable:set_widget(widget)
  33. end
  34. --- Set the background of the transient
  35. -- @param c The background to use. This must either be a cairo pattern object,
  36. -- nil or a string that gears.color() understands.
  37. function transient:set_bg(c)
  38. self._drawable:set_bg(c)
  39. end
  40. --- Set the foreground of the transient
  41. -- @param c The foreground to use. This must either be a cairo pattern object,
  42. -- nil or a string that gears.color() understands.
  43. function transient:set_fg(c)
  44. self._drawable:set_fg(c)
  45. end
  46. for _, k in pairs{ "buttons", "struts", "geometry", "get_xproperty", "set_xproperty" } do
  47. transient[k] = function(self, ...)
  48. return self.drawin[k](self.drawin, ...)
  49. end
  50. end
  51. local function setup_signals(_transient)
  52. local w = _transient.drawin
  53. local function clone_signal(name)
  54. _transient:add_signal(name)
  55. -- When "name" is emitted on transient.drawin, also emit it on transient
  56. w:connect_signal(name, function(_, ...)
  57. _transient:emit_signal(name, ...)
  58. end)
  59. end
  60. clone_signal("property::border_color")
  61. clone_signal("property::border_width")
  62. clone_signal("property::height")
  63. clone_signal("property::ontop")
  64. clone_signal("property::opacity")
  65. clone_signal("property::struts")
  66. clone_signal("property::visible")
  67. clone_signal("property::width")
  68. clone_signal("property::x")
  69. clone_signal("property::y")
  70. local d = _transient._drawable
  71. local function clone_signal(name)
  72. _transient:add_signal(name)
  73. -- When "name" is emitted on transient.drawin, also emit it on transient
  74. d:connect_signal(name, function(_, ...)
  75. _transient:emit_signal(name, ...)
  76. end)
  77. end
  78. clone_signal("property::surface")
  79. end
  80. --- Show the transient window according to the timeout set when creating the
  81. -- transient window
  82. function transient:show()
  83. -- self:top_left()
  84. if not self.visible then
  85. self.visible = true
  86. local mytimer = timer({ timeout = self.timeout })
  87. mytimer:connect_signal("timeout", function ()
  88. if self.visible == true then
  89. self.visible=false
  90. mytimer:stop()
  91. end
  92. end)
  93. mytimer:start()
  94. end
  95. end
  96. function transient:top_left()
  97. local current_screen = mouse.screen
  98. local geometry
  99. if self.parent then
  100. geometry = self.parent:geometry()
  101. else
  102. geometry = screen[current_screen].workarea
  103. end
  104. self:geometry({x=geometry.x, y=geometry.y})
  105. end
  106. function transient:top_center()
  107. local current_screen = mouse.screen
  108. local geometry
  109. if self.parent then
  110. geometry = self.parent:geometry()
  111. else
  112. geometry = screen[current_screen].workarea
  113. end
  114. local w = self.width
  115. local h = self.height
  116. local x = geometry.x + geometry.width/2 - w/2
  117. self:geometry({x=x, y=geometry.y})
  118. end
  119. function transient:top_right()
  120. local current_screen = mouse.screen
  121. local geometry
  122. if self.parent then
  123. geometry = self.parent:geometry()
  124. else
  125. geometry = screen[current_screen].workarea
  126. end
  127. local w = self.width
  128. local h = self.height
  129. local x = geometry.x + geometry.width - w
  130. self:geometry({x=x, y=geometry.y})
  131. end
  132. function transient:center()
  133. local current_screen = mouse.screen
  134. local geometry
  135. if self.parent then
  136. geometry = self.parent:geometry()
  137. else
  138. geometry = screen[current_screen].workarea
  139. end
  140. local w = self.width
  141. local h = self.height
  142. local x,y = 0
  143. x = ((geometry.width /2) + geometry.x) - w/2
  144. y = ((geometry.height /2) + geometry.y) - h/2
  145. self:geometry({x=x, y=y})
  146. end
  147. function transient:bottom_left()
  148. local current_screen = mouse.screen
  149. local geometry
  150. if self.parent then
  151. geometry = self.parent:geometry()
  152. else
  153. geometry = screen[current_screen].workarea
  154. end
  155. local w = self.width
  156. local h = self.height
  157. local x = geometry.x
  158. local y = geometry.y + geometry.height - h
  159. self:geometry({x=x, y=y})
  160. end
  161. function transient:bottom_center()
  162. local current_screen = mouse.screen
  163. local geometry
  164. if self.parent then
  165. geometry = self.parent:geometry()
  166. else
  167. geometry = screen[current_screen].workarea
  168. end
  169. local w = self.width
  170. local h = self.height
  171. local x = geometry.x + geometry.width/2 - w/2
  172. local y = geometry.y + geometry.height - h
  173. self:geometry({x=x, y=y})
  174. end
  175. function transient:bottom_right()
  176. local current_screen = mouse.screen
  177. local geometry
  178. if self.parent then
  179. geometry = self.parent:geometry()
  180. else
  181. geometry = screen[current_screen].workarea
  182. end
  183. local w = self.width
  184. local h = self.height
  185. local x = geometry.x + geometry.width - w
  186. local y = geometry.y + geometry.height - h
  187. self:geometry({x=x, y=y})
  188. end
  189. function transient:center_right()
  190. local current_screen = mouse.screen
  191. local geometry
  192. if self.parent then
  193. geometry = self.parent:geometry()
  194. else
  195. geometry = screen[current_screen].workarea
  196. end
  197. local w = self.width
  198. local h = self.height
  199. local x = geometry.x + geometry.width - w
  200. local y = geometry.y + geometry.height/2 - h/2
  201. self:geometry({x=x, y=y})
  202. end
  203. function transient:center_left()
  204. local current_screen = mouse.screen
  205. local geometry
  206. if self.parent then
  207. geometry = self.parent:geometry()
  208. else
  209. geometry = screen[current_screen].workarea
  210. end
  211. local w = self.width
  212. local h = self.height
  213. local x = geometry.x
  214. local y = geometry.y + geometry.height/2 - h/2
  215. self:geometry({x=x, y=y})
  216. end
  217. local function new(args)
  218. local ret = object()
  219. local w = capi.drawin(args)
  220. ret.drawin = w
  221. ret._drawable = transient.drawable(w.drawable, ret)
  222. if args.parent then
  223. ret.parent = args.parent
  224. end
  225. if args.timeout then
  226. ret.timeout = args.timeout
  227. else
  228. ret.timeout = 2
  229. end
  230. for k, v in pairs(transient) do
  231. if type(v) == "function" then
  232. ret[k] = v
  233. end
  234. end
  235. setup_signals(ret)
  236. ret.draw = ret._drawable.draw
  237. ret.widget_at = function(_, widget, x, y, width, height)
  238. return ret._drawable:widget_at(widget, x, y, width, height)
  239. end
  240. -- Set the default background
  241. ret:set_bg(args.bg or beautiful.bg_normal)
  242. ret:set_fg(args.fg or beautiful.fg_normal)
  243. -- Make sure the transient is drawn at least once
  244. ret.draw()
  245. -- Redirect all non-existing indexes to the "real" drawin
  246. setmetatable(ret, {
  247. __index = w,
  248. __newindex = w
  249. })
  250. ret.visible=false
  251. -- if args.position then
  252. -- if position == "center" then
  253. -- self:center()
  254. -- elseif position == "top-left" then
  255. -- self:top_left()
  256. -- elseif position == "top-center" then
  257. -- self:top_center()
  258. -- elseif position == "top-right" then
  259. -- self:top_right()
  260. -- elseif position == "bottom-left" then
  261. -- self:bottom_left()
  262. -- elseif position == "bottom-center" then
  263. -- self:bottom_center()
  264. -- elseif position == "bottom-right" then
  265. -- self:bottom_right()
  266. -- end
  267. -- end
  268. return ret
  269. end
  270. --- Redraw a transient. You should never have to call this explicitely because it is
  271. -- automatically called when needed.
  272. -- @param transient
  273. -- @name draw
  274. -- @class function
  275. --- Widget box object.
  276. -- Every transient "inherits" from a drawin and you can use all of drawin's
  277. -- functions directly on this as well. When creating a transient, you can specify a
  278. -- "fg" and a "bg" color as keys in the table that is passed to the constructor.
  279. -- All other arguments will be passed to drawin's constructor.
  280. -- @class table
  281. -- @name drawin
  282. function transient.mt:__call(...)
  283. return new(...)
  284. end
  285. return setmetatable(transient, transient.mt)
  286. -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80