mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-13 20:25:53 +08:00
[feat] add privacy unlock controls and remote relocking
This commit is contained in:
1 parent
d1e4a31efb
commit
ea3a2e1faa
41 files changed
+470
-72
No files matched your search
@@ -200,6 +200,7 @@ class MacPrivacyBackend final : public PrivacyBackend {
|
||||
const auto caps = Query();
|
||||
if (!caps.overlay) { error = caps.reason; return false; }
|
||||
block_input_ = block_input;
|
||||
allow_local_unlock_ = text.allow_local_unlock;
|
||||
emergency_ = false;
|
||||
tap_failed_ = false;
|
||||
CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) |
|
||||
@@ -239,7 +240,8 @@ class MacPrivacyBackend final : public PrivacyBackend {
|
||||
m.frame = screen.frame;
|
||||
NSView* content = CreateMacPrivacyCoverView(
|
||||
NSMakeRect(0, 0, m.frame.size.width, m.frame.size.height),
|
||||
[NSString stringWithUTF8String:text.unlock_hint.c_str()]);
|
||||
[NSString stringWithUTF8String:(text.allow_local_unlock ? text.unlock_hint : text.locked_hint).c_str()],
|
||||
text.allow_local_unlock);
|
||||
if (!content) {
|
||||
state->failure = "Could not load the CrossDesk privacy screen logo";
|
||||
break;
|
||||
@@ -260,6 +262,17 @@ class MacPrivacyBackend final : public PrivacyBackend {
|
||||
});
|
||||
return true;
|
||||
}
|
||||
void UpdateText(const PrivacyScreenText& text) override {
|
||||
allow_local_unlock_ = text.allow_local_unlock;
|
||||
auto state = state_;
|
||||
OnMain([state, text] {
|
||||
std::lock_guard lock(state->mutex);
|
||||
for (const auto& monitor : state->monitors)
|
||||
UpdateMacPrivacyCoverView(monitor.cover.contentView,
|
||||
[NSString stringWithUTF8String:(text.allow_local_unlock ? text.unlock_hint : text.locked_hint).c_str()],
|
||||
text.allow_local_unlock);
|
||||
});
|
||||
}
|
||||
void Recover() override {
|
||||
if (tap_) { CGEventTapEnable(tap_, false); CFMachPortInvalidate(tap_); }
|
||||
if (tap_source_) {
|
||||
@@ -359,7 +372,7 @@ class MacPrivacyBackend final : public PrivacyBackend {
|
||||
CGEventGetIntegerValueField(event, kCGEventSourceUnixProcessID) == getpid()) return event;
|
||||
const auto flags = CGEventGetFlags(event);
|
||||
const auto chord = kCGEventFlagMaskControl | kCGEventFlagMaskAlternate | kCGEventFlagMaskShift;
|
||||
if (type == kCGEventKeyDown && (flags & chord) == chord &&
|
||||
if (self->allow_local_unlock_ && type == kCGEventKeyDown && (flags & chord) == chord &&
|
||||
CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 53) {
|
||||
self->emergency_ = true;
|
||||
return nullptr;
|
||||
@@ -372,6 +385,7 @@ class MacPrivacyBackend final : public PrivacyBackend {
|
||||
CFMachPortRef tap_ = nullptr;
|
||||
CFRunLoopSourceRef tap_source_ = nullptr;
|
||||
bool block_input_ = false;
|
||||
bool allow_local_unlock_ = true;
|
||||
bool emergency_ = false;
|
||||
bool tap_failed_ = false;
|
||||
};
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
namespace crossdesk {
|
||||
// Returns nil if the CrossDesk icon resource cannot be loaded.
|
||||
NSView* CreateMacPrivacyCoverView(NSRect frame, NSString* unlock_hint);
|
||||
NSView* CreateMacPrivacyCoverView(NSRect frame, NSString* hint, bool allow_local_unlock = true);
|
||||
void UpdateMacPrivacyCoverView(NSView* view, NSString* hint, bool allow_local_unlock);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -52,6 +52,7 @@ CGFloat TextHeight(NSAttributedString* text, CGFloat width) {
|
||||
@interface CrossDeskPrivacyCoverView : NSView
|
||||
@property(nonatomic, strong) NSImage* logo;
|
||||
@property(nonatomic, copy) NSString* unlockHint;
|
||||
@property(nonatomic) BOOL allowLocalUnlock;
|
||||
@end
|
||||
|
||||
@implementation CrossDeskPrivacyCoverView
|
||||
@@ -77,7 +78,7 @@ CGFloat TextHeight(NSAttributedString* text, CGFloat width) {
|
||||
const CGFloat logo_size = std::ceil(brand.size.width);
|
||||
const CGFloat brand_height = TextHeight(brand, logo_size);
|
||||
const CGFloat hint_height = TextHeight(hint, text_width);
|
||||
const CGFloat shortcut_height = TextHeight(shortcut, text_width);
|
||||
const CGFloat shortcut_height = self.allowLocalUnlock ? TextHeight(shortcut, text_width) : 0;
|
||||
const CGFloat bottom = height - margin;
|
||||
const CGFloat logo_top = bottom - brand_height - 6 * scale - logo_size;
|
||||
[self.logo drawInRect:NSMakeRect(margin, logo_top, logo_size, logo_size)
|
||||
@@ -86,19 +87,26 @@ CGFloat TextHeight(NSAttributedString* text, CGFloat width) {
|
||||
[brand drawWithRect:NSMakeRect(margin, bottom - brand_height, logo_size, brand_height)
|
||||
options:kTextOptions];
|
||||
const CGFloat text_left = margin + logo_size + 24 * scale;
|
||||
[hint drawWithRect:NSMakeRect(text_left, bottom - shortcut_height - 12 * scale - hint_height,
|
||||
[hint drawWithRect:NSMakeRect(text_left, bottom - shortcut_height - (self.allowLocalUnlock ? 12 * scale : 0) - hint_height,
|
||||
text_width, hint_height) options:kTextOptions];
|
||||
[shortcut drawWithRect:NSMakeRect(text_left, bottom - shortcut_height,
|
||||
if (self.allowLocalUnlock) [shortcut drawWithRect:NSMakeRect(text_left, bottom - shortcut_height,
|
||||
text_width, shortcut_height) options:kTextOptions];
|
||||
}
|
||||
@end
|
||||
|
||||
namespace crossdesk {
|
||||
NSView* CreateMacPrivacyCoverView(NSRect frame, NSString* unlock_hint) {
|
||||
void UpdateMacPrivacyCoverView(NSView* view, NSString* hint, bool allow_local_unlock) {
|
||||
auto* cover = static_cast<CrossDeskPrivacyCoverView*>(view);
|
||||
cover.unlockHint = hint;
|
||||
cover.allowLocalUnlock = allow_local_unlock;
|
||||
cover.needsDisplay = YES;
|
||||
}
|
||||
NSView* CreateMacPrivacyCoverView(NSRect frame, NSString* unlock_hint, bool allow_local_unlock) {
|
||||
NSImage* logo = LoadPrivacyLogo();
|
||||
if (!logo) return nil;
|
||||
auto* view = [[CrossDeskPrivacyCoverView alloc] initWithFrame:frame];
|
||||
view.logo = logo;
|
||||
view.allowLocalUnlock = allow_local_unlock;
|
||||
view.unlockHint = unlock_hint ?: @"To turn off the privacy screen, press";
|
||||
view.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
return view;
|
||||
|
||||
Reference in new issue
Block a user