Skip to content

Commit

Permalink
Merge pull request #1450 from contour-terminal/fix/race-on-mouseMove
Browse files Browse the repository at this point in the history
Fix thread safety issue on mouse move event handling
  • Loading branch information
christianparpart authored Feb 3, 2024
2 parents cc5193a + 9aa91e1 commit f8a3229
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 4 deletions.
1 change: 1 addition & 0 deletions metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
<li>Fixes `scripts/install-deps.sh` for openSuSE (Tumbleweed) to install the correct dependencies.</li>
<li>Fixes missing dependencies for release .deb packages (#1397).</li>
<li>Fixes legacy keyboard input protocol not reporting non-Alt modifier (#1411).</li>
<li>Fixes thread safety issue on mouse move event handling (#1444).</li>
<li>Digitally sign MacOS release binaries using a valid Apple ID.</li>
<li>Add support for authenticating to SSH servers with a private key without a password and without requesting for one - also allow password retry (#1425).</li>
<li>Default history limit is now 1000 lines rather than 0 lines.</li>
Expand Down
14 changes: 10 additions & 4 deletions src/contour/TerminalSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <crispy/StackTrace.h>
#include <crispy/assert.h>
#include <crispy/utils.h>

#include <QtCore/QDebug>
#include <QtCore/QFileInfo>
Expand Down Expand Up @@ -827,7 +828,9 @@ void TerminalSession::sendMousePressEvent(Modifiers modifiers,

terminal().tick(steady_clock::now());

if (terminal().sendMousePressEvent(modifiers, button, pixelPosition, uiHandledHint))
if (crispy::locked(_terminal, [&]() {
return _terminal.sendMousePressEvent(modifiers, button, pixelPosition, uiHandledHint);
}))
return;

auto const sanitizedModifier = modifiers.contains(_config.bypassMouseProtocolModifiers)
Expand All @@ -852,7 +855,8 @@ void TerminalSession::sendMouseMoveEvent(vtbackend::Modifiers modifiers,
terminal().tick(steady_clock::now());

auto constexpr UiHandledHint = false;
terminal().sendMouseMoveEvent(modifiers, pos, pixelPosition, UiHandledHint);
crispy::locked(_terminal,
[&]() { _terminal.sendMouseMoveEvent(modifiers, pos, pixelPosition, UiHandledHint); });

if (pos != _currentMousePosition)
{
Expand All @@ -871,8 +875,10 @@ void TerminalSession::sendMouseReleaseEvent(Modifiers modifiers,
{
terminal().tick(steady_clock::now());

auto const uiHandledHint = false;
terminal().sendMouseReleaseEvent(modifiers, button, pixelPosition, uiHandledHint);
crispy::locked(_terminal, [&]() {
auto const uiHandledHint = false;
_terminal.sendMouseReleaseEvent(modifiers, button, pixelPosition, uiHandledHint);
});
scheduleRedraw();
}

Expand Down
1 change: 1 addition & 0 deletions src/crispy/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#if (defined(__cpp_concepts) && __cpp_concepts >= 201500L) \
&& (defined(__cpp_lib_concepts) && __cpp_lib_concepts >= 202002L)
#define CRISPY_CONCEPTS_SUPPORTED
#define CRISPY_REQUIRES(x) requires x
#else
#define CRISPY_REQUIRES(x) /*!*/
Expand Down
27 changes: 27 additions & 0 deletions src/crispy/utils.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <crispy/defines.h>
#include <crispy/escape.h>

#include <fmt/format.h>
Expand All @@ -11,13 +12,18 @@
#include <filesystem>
#include <fstream>
#include <functional>
#include <mutex>
#include <optional>
#include <sstream>
#include <string>
#include <string_view>
#include <unordered_map>
#include <vector>

#if defined(CRISPY_CONCEPTS_SUPPORTED)
#include <concepts>
#endif

namespace crispy
{

Expand Down Expand Up @@ -297,6 +303,27 @@ class finally // NOLINT(readability-identifier-naming)
std::function<void()> _hook {};
};

#if defined(CRISPY_CONCEPTS_SUPPORTED)

// clang-format off
template <typename T>
concept LockableConcept = requires(T t)
{
{ t.lock() } -> std::same_as<void>;
{ t.unlock() } -> std::same_as<void>;
};
// clang-format on

#endif

template <typename L, typename F>
CRISPY_REQUIRES(LockableConcept<L>)
auto locked(L& lockable, F const& f)
{
auto const _ = std::scoped_lock { lockable };
return f();
}

inline std::optional<unsigned> fromHexDigit(char value)
{
if ('0' <= value && value <= '9')
Expand Down

0 comments on commit f8a3229

Please sign in to comment.