Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/osutils/macutils/AppKitImpl.mm')
-rw-r--r--src/gui/osutils/macutils/AppKitImpl.mm232
1 files changed, 232 insertions, 0 deletions
diff --git a/src/gui/osutils/macutils/AppKitImpl.mm b/src/gui/osutils/macutils/AppKitImpl.mm
new file mode 100644
index 000000000..077dd71a6
--- /dev/null
+++ b/src/gui/osutils/macutils/AppKitImpl.mm
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2016 Lennart Glauer <mail@lennart-glauer.de>
+ * Copyright (C) 2017 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#import "AppKitImpl.h"
+
+#import <AppKit/NSWorkspace.h>
+#import <CoreVideo/CVPixelBuffer.h>
+
+@implementation AppKitImpl
+
+- (id) initWithObject:(AppKit*)appkit
+{
+ self = [super init];
+ if (self) {
+ m_appkit = appkit;
+ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:static_cast<id>(self)
+ selector:@selector(didDeactivateApplicationObserver:)
+ name:NSWorkspaceDidDeactivateApplicationNotification
+ object:nil];
+
+ [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:static_cast<id>(self)
+ selector:@selector(userSwitchHandler:)
+ name:NSWorkspaceSessionDidResignActiveNotification
+ object:nil];
+ }
+ return self;
+}
+
+//
+// Update last active application property
+//
+- (void) didDeactivateApplicationObserver:(NSNotification*) notification
+{
+ NSDictionary* userInfo = notification.userInfo;
+ NSRunningApplication* app = userInfo[NSWorkspaceApplicationKey];
+
+ if (app.processIdentifier != [self ownProcessId]) {
+ self.lastActiveApplication = app;
+ }
+}
+
+//
+// Get process id of frontmost application (-> keyboard input)
+//
+- (pid_t) activeProcessId
+{
+ return [NSWorkspace sharedWorkspace].frontmostApplication.processIdentifier;
+}
+
+//
+// Get process id of own process
+//
+- (pid_t) ownProcessId
+{
+ return [NSProcessInfo processInfo].processIdentifier;
+}
+
+//
+// Activate application by process id
+//
+- (bool) activateProcess:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
+}
+
+//
+// Hide application by process id
+//
+- (bool) hideProcess:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app hide];
+}
+
+//
+// Get application hidden state by process id
+//
+- (bool) isHidden:(pid_t) pid
+{
+ NSRunningApplication* app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
+ return [app isHidden];
+}
+
+//
+// Get state of macOS Dark Mode color scheme
+//
+- (bool) isDarkMode
+{
+ NSDictionary* dict = [[NSUserDefaults standardUserDefaults] persistentDomainForName:NSGlobalDomain];
+ id style = [dict objectForKey:@"AppleInterfaceStyle"];
+ return ( style && [style isKindOfClass:[NSString class]]
+ && NSOrderedSame == [style caseInsensitiveCompare:@"dark"] );
+}
+
+//
+// Notification for user switch
+//
+- (void) userSwitchHandler:(NSNotification*) notification
+{
+ if ([[notification name] isEqualToString:NSWorkspaceSessionDidResignActiveNotification] && m_appkit)
+ {
+ emit m_appkit->lockDatabases();
+ }
+}
+
+//
+// Check if accessibility is enabled, may show an popup asking for permissions
+//
+- (bool) enableAccessibility
+{
+ // Request accessibility permissions for Auto-Type type on behalf of the user
+ NSDictionary* opts = @{static_cast<id>(kAXTrustedCheckOptionPrompt): @YES};
+ return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef>(opts));
+}
+
+//
+// Check if screen recording is enabled, may show an popup asking for permissions
+//
+- (bool) enableScreenRecording
+{
+ if (@available(macOS 10.15, *)) {
+ // Request screen recording permission on macOS 10.15+
+ // This is necessary to get the current window title
+ CGDisplayStreamRef stream = CGDisplayStreamCreate(CGMainDisplayID(), 1, 1, kCVPixelFormatType_32BGRA, nil,
+ ^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
+ IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
+ Q_UNUSED(status);
+ Q_UNUSED(displayTime);
+ Q_UNUSED(frameSurface);
+ Q_UNUSED(updateRef);
+ });
+ if (stream) {
+ CFRelease(stream);
+ } else {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+- (void) toggleForegroundApp:(bool) foreground
+{
+ ProcessSerialNumber psn = {0, kCurrentProcess};
+ if (foreground) {
+ TransformProcessType(&psn, kProcessTransformToForegroundApplication);
+ } else {
+ TransformProcessType(&psn, kProcessTransformToUIElementApplication);
+ }
+}
+
+@end
+
+//
+// ------------------------- C++ Trampolines -------------------------
+//
+
+AppKit::AppKit(QObject* parent) : QObject(parent)
+{
+ self = [[AppKitImpl alloc] initWithObject:this];
+}
+
+AppKit::~AppKit()
+{
+ [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:static_cast<id>(self)];
+ [static_cast<id>(self) dealloc];
+}
+
+pid_t AppKit::lastActiveProcessId()
+{
+ return [static_cast<id>(self) lastActiveApplication].processIdentifier;
+}
+
+pid_t AppKit::activeProcessId()
+{
+ return [static_cast<id>(self) activeProcessId];
+}
+
+pid_t AppKit::ownProcessId()
+{
+ return [static_cast<id>(self) ownProcessId];
+}
+
+bool AppKit::activateProcess(pid_t pid)
+{
+ return [static_cast<id>(self) activateProcess:pid];
+}
+
+bool AppKit::hideProcess(pid_t pid)
+{
+ return [static_cast<id>(self) hideProcess:pid];
+}
+
+bool AppKit::isHidden(pid_t pid)
+{
+ return [static_cast<id>(self) isHidden:pid];
+}
+
+bool AppKit::isDarkMode()
+{
+ return [static_cast<id>(self) isDarkMode];
+}
+
+bool AppKit::enableAccessibility()
+{
+ return [static_cast<id>(self) enableAccessibility];
+}
+
+bool AppKit::enableScreenRecording()
+{
+ return [static_cast<id>(self) enableScreenRecording];
+}
+
+void AppKit::toggleForegroundApp(bool foreground)
+{
+ [static_cast<id>(self) toggleForegroundApp:foreground];
+}