feat(w.w.slider): Add signals for the dragging state

When trying to hook up the slider to an external value, one would
usually have two data streams:

- `property::value` -> set external value
- external value changed -> `.value = new_value`

The problem is that without manual intervention, these two streams form
a loop, as setting `.value` also emits `property::value`.

The new set of signals is disconnected from the `value` property and its
signal and allows for more fine grained inspection of the dragging
state.

Signed-off-by: Lucas Schwiderski <lucas@lschwiderski.de>
This commit is contained in:
Lucas Schwiderski 2021-12-22 20:38:22 +01:00
parent 70524e72fa
commit dc5013dfb9
No known key found for this signature in database
GPG Key ID: AA12679AAA6DF4D8
1 changed files with 36 additions and 0 deletions

View File

@ -244,6 +244,28 @@ local slider = {mt={}}
-- @beautiful beautiful.slider_bar_active_color -- @beautiful beautiful.slider_bar_active_color
-- @param color -- @param color
--- Emitted when the user starts dragging the handle.
--
-- @signal drag_start
-- @tparam number value The current value
--- Emitted for every mouse move while the handle is being dragged.
--
-- This signal is only emitted by the user dragging the handle. It is therefore
-- preferrable over `property::value`, as it cannot create a loop when trying to
-- hook up the slider as representation of an external value (e.g. system
-- volume).
--
-- @signal drag
-- @tparam number value The current value
--- Emitted when the user stops dragging the handle.
--
-- This signal is emitted when the user releases the mouse button after dragging
-- the handle.
--
-- @signal drag_end
-- @tparam number value The current value
local properties = { local properties = {
-- Handle -- Handle
@ -303,6 +325,14 @@ function slider:set_value(value)
end end
end end
--- Returns `true` while the user is dragging the handle.
--
-- @method is_dragging
-- @treturn boolean
function slider:is_dragging()
return self._private.is_dragging
end
local function get_extremums(self) local function get_extremums(self)
local min = self._private.minimum or properties.minimum local min = self._private.minimum or properties.minimum
local max = self._private.maximum or properties.maximum local max = self._private.maximum or properties.maximum
@ -504,17 +534,23 @@ local function mouse_press(self, x, y, button_id, _, geo)
move_handle(self, width, x, y) move_handle(self, width, x, y)
self._private.is_dragging = true
self:emit_signal("drag_start", self.value)
-- Calculate a matrix transforming from screen coordinates into widget coordinates -- Calculate a matrix transforming from screen coordinates into widget coordinates
local wgeo = geo.drawable.drawable:geometry() local wgeo = geo.drawable.drawable:geometry()
local matrix = matrix_from_device:translate(-wgeo.x, -wgeo.y) local matrix = matrix_from_device:translate(-wgeo.x, -wgeo.y)
capi.mousegrabber.run(function(mouse) capi.mousegrabber.run(function(mouse)
if not mouse.buttons[1] then if not mouse.buttons[1] then
self._private.is_dragging = false
self:emit_signal("drag_end", self.value)
return false return false
end end
-- Calculate the point relative to the widget -- Calculate the point relative to the widget
move_handle(self, width, matrix:transform_point(mouse.x, mouse.y)) move_handle(self, width, matrix:transform_point(mouse.x, mouse.y))
self:emit_signal("drag", self.value)
return true return true
end,"fleur") end,"fleur")