drawin: Only redraw on move with translucent background
If a drawable has an opaque background, we don't need pseudo transparency and thus its content don't change when it is moved. However, when we need pseudo transparency, then we have to redraw the drawable to apply the new background. Previously we just always did the redraw. This commit adds a helper function gears.color.create_opaque_pattern() that analyzes a cairo pattern for transparency. We use this new function to only redraw-on-move when there is actual pseudo transparency in effect. Otherwise, this redraw can be skipped. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
40e28be700
commit
1924ee9e6e
|
@ -202,6 +202,57 @@ function color.create_pattern(col)
|
||||||
return color.create_solid_pattern(col)
|
return color.create_solid_pattern(col)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if a pattern is opaque.
|
||||||
|
-- A pattern is transparent if the background on which it gets drawn (with
|
||||||
|
-- operator OVER) doesn't influence the visual result.
|
||||||
|
-- @param col An argument that create_pattern() accepts
|
||||||
|
-- @return The pattern if it is surely opaque, else nil
|
||||||
|
function color.create_opaque_pattern(col)
|
||||||
|
local pattern = color.create_pattern(col)
|
||||||
|
local type = pattern:get_type()
|
||||||
|
local extend = pattern:get_extend()
|
||||||
|
|
||||||
|
if type == "SOLID" then
|
||||||
|
local status, r, g, b, a = pattern:get_rgba()
|
||||||
|
if a ~= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return pattern
|
||||||
|
elseif type == "SURFACE" then
|
||||||
|
if pattern:get_surface():get_content() ~= "COLOR" then
|
||||||
|
-- The surface has an alpha channel which *might* be non-opaque
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Only the "NONE" extend mode is forbidden, everything else doesn't
|
||||||
|
-- introduce transparent parts
|
||||||
|
if pattern:get_extend() == "NONE" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
return pattern
|
||||||
|
elseif type == "LINEAR" then
|
||||||
|
local status, stops = pattern:get_color_stop_count()
|
||||||
|
|
||||||
|
-- No color stops or extend NONE -> pattern *might* contain transparency
|
||||||
|
if stops == 0 or pattern:get_extend() == "NONE" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Now check if any of the color stops contain transparency
|
||||||
|
for i = 0, stops - 1 do
|
||||||
|
local status, offset, r, g, b, a = pattern:get_color_stop_rgba(i)
|
||||||
|
if a ~= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Unknown type, e.g. mesh or raster source or unsupported type (radial
|
||||||
|
-- gradients can do weird self-intersections)
|
||||||
|
end
|
||||||
|
|
||||||
function color.mt:__call(...)
|
function color.mt:__call(...)
|
||||||
return color.create_pattern(...)
|
return color.create_pattern(...)
|
||||||
end
|
end
|
||||||
|
|
|
@ -129,6 +129,24 @@ function drawable:set_bg(c)
|
||||||
if type(c) == "string" or type(c) == "table" then
|
if type(c) == "string" or type(c) == "table" then
|
||||||
c = color(c)
|
c = color(c)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- If the background is completely opaque, we don't need to redraw when
|
||||||
|
-- the drawable is moved
|
||||||
|
-- XXX: This isn't needed when awesome.composite_manager_running is true,
|
||||||
|
-- but a compositing manager could stop/start and we'd have to properly
|
||||||
|
-- handle this. So for now we choose the lazy approach.
|
||||||
|
local redraw_on_move = not color.create_opaque_pattern(c)
|
||||||
|
if self._redraw_on_move ~= redraw_on_move then
|
||||||
|
self._redraw_on_move = redraw_on_move
|
||||||
|
if redraw_on_move then
|
||||||
|
self.drawable:connect_signal("property::x", self.draw)
|
||||||
|
self.drawable:connect_signal("property::y", self.draw)
|
||||||
|
else
|
||||||
|
self.drawable:disconnect_signal("property::x", self.draw)
|
||||||
|
self.drawable:disconnect_signal("property::y", self.draw)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self.background_color = c
|
self.background_color = c
|
||||||
self.draw()
|
self.draw()
|
||||||
end
|
end
|
||||||
|
@ -235,9 +253,10 @@ function drawable.new(d, widget_arg)
|
||||||
end
|
end
|
||||||
drawables[ret.draw] = true
|
drawables[ret.draw] = true
|
||||||
d:connect_signal("property::surface", ret.draw)
|
d:connect_signal("property::surface", ret.draw)
|
||||||
-- We don't need width/height, because this case emits property::surface
|
|
||||||
d:connect_signal("property::x", ret.draw)
|
-- Currently we aren't redrawing on move (signals not connected).
|
||||||
d:connect_signal("property::y", ret.draw)
|
-- :set_bg() will later recompute this.
|
||||||
|
ret._redraw_on_move = false
|
||||||
|
|
||||||
-- Set the default background
|
-- Set the default background
|
||||||
ret:set_bg(beautiful.bg_normal)
|
ret:set_bg(beautiful.bg_normal)
|
||||||
|
|
Loading…
Reference in New Issue