Compare commits

..

5 Commits

6 changed files with 119 additions and 19 deletions
@@ -1,11 +1,36 @@
#include "mouse_controller.h"
#include <ApplicationServices/ApplicationServices.h>
#include <algorithm>
#include <chrono>
#include <cstdlib>
#include "rd_log.h"
namespace crossdesk {
namespace {
constexpr auto kDoubleClickInterval = std::chrono::milliseconds(500);
constexpr int kDoubleClickMaxDistance = 8;
constexpr int kMaxClickState = 3;
bool IsWithinClickDistance(int x1, int y1, int x2, int y2) {
return std::abs(x1 - x2) <= kDoubleClickMaxDistance &&
std::abs(y1 - y2) <= kDoubleClickMaxDistance;
}
void SetClickState(CGEventRef event, int click_state) {
if (!event) {
return;
}
CGEventSetIntegerValueField(
event, kCGMouseEventClickState,
std::max(1, std::min(click_state, kMaxClickState)));
}
} // namespace
MouseController::MouseController() {}
@@ -19,6 +44,36 @@ int MouseController::Init(std::vector<DisplayInfo> display_info_list) {
int MouseController::Destroy() { return 0; }
int MouseController::BeginClick(ClickTracker& tracker, int x, int y) {
const auto now = std::chrono::steady_clock::now();
const bool continues_previous_click =
tracker.has_last_down &&
now - tracker.last_down_time <= kDoubleClickInterval &&
IsWithinClickDistance(tracker.last_down_x, tracker.last_down_y, x, y);
tracker.click_state = continues_previous_click
? std::min(tracker.click_state + 1, kMaxClickState)
: 1;
tracker.active_click_state = tracker.click_state;
tracker.has_last_down = true;
tracker.last_down_time = now;
tracker.last_down_x = x;
tracker.last_down_y = y;
return tracker.active_click_state;
}
int MouseController::EndClick(ClickTracker& tracker, int x, int y) {
const int click_state = tracker.active_click_state;
if (!IsWithinClickDistance(tracker.last_down_x, tracker.last_down_y, x, y)) {
tracker.has_last_down = false;
tracker.click_state = 0;
tracker.active_click_state = 1;
}
return click_state;
}
int MouseController::SendMouseCommand(RemoteAction remote_action,
int display_index) {
if (remote_action.type != ControlType::mouse) {
@@ -41,58 +96,69 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
const float normalized_x = std::clamp(remote_action.m.x, 0.0f, 1.0f);
const float normalized_y = std::clamp(remote_action.m.y, 0.0f, 1.0f);
int mouse_pos_x =
normalized_x * display_info.width + display_info.left;
int mouse_pos_y =
normalized_y * display_info.height + display_info.top;
int mouse_pos_x = normalized_x * display_info.width + display_info.left;
int mouse_pos_y = normalized_y * display_info.height + display_info.top;
CGEventRef mouse_event = nullptr;
CGEventType mouse_type;
CGMouseButton mouse_button;
CGPoint mouse_point = CGPointMake(mouse_pos_x, mouse_pos_y);
int click_state = 1;
switch (remote_action.m.flag) {
case MouseFlag::left_down:
mouse_type = kCGEventLeftMouseDown;
left_dragging_ = true;
click_state = BeginClick(left_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonLeft);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::left_up:
mouse_type = kCGEventLeftMouseUp;
left_dragging_ = false;
click_state = EndClick(left_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonLeft);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::right_down:
mouse_type = kCGEventRightMouseDown;
right_dragging_ = true;
click_state = BeginClick(right_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonRight);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::right_up:
mouse_type = kCGEventRightMouseUp;
right_dragging_ = false;
click_state = EndClick(right_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonRight);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::middle_down:
mouse_type = kCGEventOtherMouseDown;
click_state = BeginClick(middle_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonCenter);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::middle_up:
mouse_type = kCGEventOtherMouseUp;
click_state = EndClick(middle_click_tracker_, mouse_pos_x, mouse_pos_y);
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
kCGMouseButtonCenter);
SetClickState(mouse_event, click_state);
break;
case MouseFlag::wheel_vertical:
mouse_event = CGEventCreateScrollWheelEvent(
NULL, kCGScrollEventUnitLine, 2, remote_action.m.s, 0);
mouse_event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine,
2, remote_action.m.s, 0);
break;
case MouseFlag::wheel_horizontal:
mouse_event = CGEventCreateScrollWheelEvent(
NULL, kCGScrollEventUnitLine, 2, 0, remote_action.m.s);
mouse_event = CGEventCreateScrollWheelEvent(NULL, kCGScrollEventUnitLine,
2, 0, remote_action.m.s);
break;
default:
if (left_dragging_) {
@@ -106,8 +172,8 @@ int MouseController::SendMouseCommand(RemoteAction remote_action,
mouse_button = kCGMouseButtonLeft;
}
mouse_event = CGEventCreateMouseEvent(NULL, mouse_type, mouse_point,
mouse_button);
mouse_event =
CGEventCreateMouseEvent(NULL, mouse_type, mouse_point, mouse_button);
break;
}
@@ -7,6 +7,7 @@
#ifndef _MOUSE_CONTROLLER_H_
#define _MOUSE_CONTROLLER_H_
#include <chrono>
#include <vector>
#include "device_controller.h"
@@ -24,9 +25,24 @@ class MouseController : public DeviceController {
virtual int SendMouseCommand(RemoteAction remote_action, int display_index);
private:
struct ClickTracker {
bool has_last_down = false;
std::chrono::steady_clock::time_point last_down_time{};
int last_down_x = 0;
int last_down_y = 0;
int click_state = 0;
int active_click_state = 1;
};
int BeginClick(ClickTracker& tracker, int x, int y);
int EndClick(ClickTracker& tracker, int x, int y);
std::vector<DisplayInfo> display_info_list_;
bool left_dragging_ = false;
bool right_dragging_ = false;
ClickTracker left_click_tracker_;
ClickTracker right_click_tracker_;
ClickTracker middle_click_tracker_;
};
} // namespace crossdesk
#endif
#endif
@@ -158,6 +158,9 @@ struct TranslationRow {
X(signal_connected, u8"已连接服务器", "Connected", u8"Подключено к серверу") \
X(signal_disconnected, u8"未连接服务器", "Disconnected", \
u8"Нет подключения к серверу") \
X(signal_tls_cert_error, u8"证书验证失败,请重新安装自托管根证书", \
"Certificate verification failed. Reinstall the self-hosted root certificate.", \
u8"Ошибка проверки сертификата. Переустановите корневой сертификат.") \
X(p2p_connected, u8"对等连接已建立", "P2P Connected", u8"P2P подключено") \
X(p2p_disconnected, u8"对等连接已断开", "P2P Disconnected", \
u8"P2P отключено") \
+4
View File
@@ -1231,6 +1231,8 @@ void Render::OnSignalStatusCb(SignalStatus status, const char* user_id,
render->signal_connected_ = false;
} else if (SignalStatus::SignalServerClosed == status) {
render->signal_connected_ = false;
} else if (SignalStatus::SignalTlsCertError == status) {
render->signal_connected_ = false;
}
} else {
if (client_id.rfind("C-", 0) != 0) {
@@ -1258,6 +1260,8 @@ void Render::OnSignalStatusCb(SignalStatus status, const char* user_id,
props->signal_connected_ = false;
} else if (SignalStatus::SignalServerClosed == status) {
props->signal_connected_ = false;
} else if (SignalStatus::SignalTlsCertError == status) {
props->signal_connected_ = false;
}
}
}
+18 -7
View File
@@ -26,20 +26,31 @@ int Render::StatusBar() {
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->AddCircleFilled(dot_pos, status_bar_height * 0.25f,
ImColor(1.0f, 1.0f, 1.0f), 100);
bool tls_cert_error =
signal_status_ == SignalStatus::SignalTlsCertError;
draw_list->AddCircleFilled(dot_pos, status_bar_height * 0.2f,
ImColor(signal_connected_ ? 0.0f : 1.0f,
signal_connected_ ? 1.0f : 0.0f, 0.0f),
tls_cert_error
? ImColor(1.0f, 0.65f, 0.0f)
: ImColor(signal_connected_ ? 0.0f : 1.0f,
signal_connected_ ? 1.0f : 0.0f,
0.0f),
100);
ImGui::SetWindowFontScale(0.6f);
const char* signal_status_text =
tls_cert_error
? localization::signal_tls_cert_error[localization_language_index_]
.c_str()
: (signal_connected_
? localization::signal_connected[localization_language_index_]
.c_str()
: localization::signal_disconnected
[localization_language_index_]
.c_str());
draw_list->AddText(
ImVec2(status_bar_width * 0.045f,
io.DisplaySize.y * (1 - STATUS_BAR_HEIGHT * 0.9f)),
ImColor(0.0f, 0.0f, 0.0f),
signal_connected_
? localization::signal_connected[localization_language_index_].c_str()
: localization::signal_disconnected[localization_language_index_]
.c_str());
ImColor(0.0f, 0.0f, 0.0f), signal_status_text);
ImGui::SetWindowFontScale(1.0f);
ImGui::EndChild();