Add macOS support and cross-platform CMake
This commit is contained in:
parent
9248f3945d
commit
471b4c7b3b
107
CMakeLists.txt
107
CMakeLists.txt
|
|
@ -12,32 +12,94 @@ set(CMAKE_AUTOMOC ON)
|
|||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
# Set Qt5 path
|
||||
set(Qt5_DIR "$ENV{HOME}/sdk/qt-5.15.2/lib/cmake/Qt5")
|
||||
# Platform detection
|
||||
if(APPLE)
|
||||
message(STATUS "Building for macOS")
|
||||
set(PLATFORM_NAME "macOS")
|
||||
elseif(UNIX)
|
||||
message(STATUS "Building for Linux")
|
||||
set(PLATFORM_NAME "Linux")
|
||||
else()
|
||||
message(WARNING "Unsupported platform")
|
||||
endif()
|
||||
|
||||
# Set Qt5 path (customize this based on your installation)
|
||||
if(APPLE)
|
||||
# macOS: Try common Qt installation paths
|
||||
if(NOT DEFINED Qt5_DIR)
|
||||
# Check MacPorts installation
|
||||
if(EXISTS "/opt/local/lib/cmake/Qt5")
|
||||
set(Qt5_DIR "/opt/local/lib/cmake/Qt5")
|
||||
# Check Homebrew installation (Intel)
|
||||
elseif(EXISTS "/usr/local/opt/qt@5/lib/cmake/Qt5")
|
||||
set(Qt5_DIR "/usr/local/opt/qt@5/lib/cmake/Qt5")
|
||||
# Check Homebrew installation (Apple Silicon)
|
||||
elseif(EXISTS "/opt/homebrew/opt/qt@5/lib/cmake/Qt5")
|
||||
set(Qt5_DIR "/opt/homebrew/opt/qt@5/lib/cmake/Qt5")
|
||||
# Check official Qt installer
|
||||
elseif(EXISTS "$ENV{HOME}/Qt/5.15.2/clang_64/lib/cmake/Qt5")
|
||||
set(Qt5_DIR "$ENV{HOME}/Qt/5.15.2/clang_64/lib/cmake/Qt5")
|
||||
# Check custom installation
|
||||
elseif(EXISTS "$ENV{HOME}/sdk/qt-5.15.2/lib/cmake/Qt5")
|
||||
set(Qt5_DIR "$ENV{HOME}/sdk/qt-5.15.2/lib/cmake/Qt5")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# Linux: Use custom path
|
||||
if(NOT DEFINED Qt5_DIR)
|
||||
set(Qt5_DIR "$ENV{HOME}/sdk/qt-5.15.2/lib/cmake/Qt5")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Find Qt5 packages
|
||||
find_package(Qt5 REQUIRED COMPONENTS
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
DBus
|
||||
)
|
||||
set(QT_COMPONENTS Core Gui Widgets)
|
||||
|
||||
# Source files
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND QT_COMPONENTS DBus)
|
||||
endif()
|
||||
|
||||
find_package(Qt5 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||
|
||||
# Common source files
|
||||
set(SOURCES
|
||||
src/main.cpp
|
||||
src/mainwindow.cpp
|
||||
src/screenlockdetector.cpp
|
||||
src/customwidget.cpp
|
||||
)
|
||||
|
||||
# Header files
|
||||
set(HEADERS
|
||||
src/mainwindow.h
|
||||
src/screenlockdetector.h
|
||||
src/customwidget.h
|
||||
)
|
||||
|
||||
# Platform-specific source files
|
||||
if(APPLE)
|
||||
# macOS specific files
|
||||
list(APPEND SOURCES
|
||||
src/screenlockdetector.cpp
|
||||
src/screenlockdetector_mac.mm
|
||||
)
|
||||
list(APPEND HEADERS
|
||||
src/screenlockdetector.h
|
||||
src/screenlockdetector_mac.h
|
||||
)
|
||||
|
||||
# Enable Objective-C++ for .mm files
|
||||
set_source_files_properties(
|
||||
src/screenlockdetector_mac.mm
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "-x objective-c++"
|
||||
)
|
||||
elseif(UNIX)
|
||||
# Linux specific files
|
||||
list(APPEND SOURCES
|
||||
src/screenlockdetector.cpp
|
||||
)
|
||||
list(APPEND HEADERS
|
||||
src/screenlockdetector.h
|
||||
)
|
||||
endif()
|
||||
|
||||
# Add executable
|
||||
add_executable(${PROJECT_NAME}
|
||||
${SOURCES}
|
||||
|
|
@ -49,14 +111,31 @@ target_link_libraries(${PROJECT_NAME}
|
|||
Qt5::Core
|
||||
Qt5::Gui
|
||||
Qt5::Widgets
|
||||
Qt5::DBus
|
||||
)
|
||||
|
||||
# Platform-specific linking
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(${PROJECT_NAME} Qt5::DBus)
|
||||
elseif(APPLE)
|
||||
# Link macOS frameworks
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
"-framework Foundation"
|
||||
"-framework Cocoa"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Set output directory
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
|
||||
)
|
||||
|
||||
# macOS specific settings
|
||||
if(APPLE)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE FALSE
|
||||
)
|
||||
endif()
|
||||
|
||||
# Install target
|
||||
install(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION bin
|
||||
|
|
@ -66,6 +145,8 @@ install(TARGETS ${PROJECT_NAME}
|
|||
message(STATUS "========================================")
|
||||
message(STATUS "Build Configuration:")
|
||||
message(STATUS "========================================")
|
||||
message(STATUS "Platform: ${PLATFORM_NAME}")
|
||||
message(STATUS "Qt5_DIR: ${Qt5_DIR}")
|
||||
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "Qt Components: ${QT_COMPONENTS}")
|
||||
message(STATUS "========================================")
|
||||
|
|
|
|||
244
README.md
244
README.md
|
|
@ -1,23 +1,33 @@
|
|||
# Qt Screen Lock Detection Demo
|
||||
|
||||
一个基于 Qt5 + CMake 的 Linux 应用程序,用于检测 Ubuntu 系统的锁屏状态,并在锁屏时自动停止所有 Paint 事件。
|
||||
一个基于 Qt5 + CMake 的跨平台应用程序,用于检测系统的锁屏状态,并在锁屏时自动停止所有 Paint 事件。
|
||||
|
||||
**支持平台:**
|
||||
- ✅ **Linux** (Ubuntu, Deepin, Fedora 等)
|
||||
- ✅ **macOS** (10.12 及以上版本)
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ **自动检测锁屏状态**:通过 DBus 监听 Linux 系统的锁屏/解锁事件
|
||||
- ✅ **自动检测锁屏状态**:
|
||||
- Linux: 通过 DBus 监听系统的锁屏/解锁事件
|
||||
- macOS: 通过 NSDistributedNotificationCenter 监听系统通知
|
||||
- ✅ **自动停止绘制**:屏幕锁定时自动停止所有 Paint 事件,节省系统资源
|
||||
- ✅ **实时动画演示**:持续的动画效果,直观展示绘制的启用/禁用状态
|
||||
- ✅ **手动控制**:提供手动启用/禁用绘制的按钮
|
||||
- ✅ **状态监控**:实时显示锁屏状态、绘制状态和帧数统计
|
||||
- ✅ **多桌面环境支持**:支持 GNOME、KDE、XFCE、Deepin DDE 等主流桌面环境
|
||||
- ✅ **多平台支持**:
|
||||
- Linux: 支持 GNOME、KDE、XFCE、Deepin DDE 等主流桌面环境
|
||||
- macOS: 原生系统通知支持
|
||||
|
||||
## 技术架构
|
||||
|
||||
### 核心组件
|
||||
|
||||
1. **ScreenLockDetector** - 锁屏检测器
|
||||
- 通过 Qt DBus 监听系统锁屏信号
|
||||
- 支持 GNOME ScreenSaver、systemd-logind 和 Deepin DDE 接口
|
||||
1. **ScreenLockDetector** - 跨平台锁屏检测器
|
||||
- **Linux**: 通过 Qt DBus 监听系统锁屏信号
|
||||
- 支持 GNOME ScreenSaver、systemd-logind 和 Deepin DDE 接口
|
||||
- **macOS**: 通过 NSDistributedNotificationCenter 监听系统通知
|
||||
- 监听 com.apple.screenIsLocked/Unlocked 通知
|
||||
- 发出锁屏/解锁信号供其他组件订阅
|
||||
|
||||
2. **CustomWidget** - 自定义绘制组件
|
||||
|
|
@ -33,69 +43,142 @@
|
|||
|
||||
### 技术栈
|
||||
|
||||
- **语言**:C++11
|
||||
- **GUI 框架**:Qt 5.15.2
|
||||
- **语言**:C++11 / Objective-C++ (macOS)
|
||||
- **GUI 框架**:Qt 5.15.2 (或更高版本)
|
||||
- **构建系统**:CMake 3.10+
|
||||
- **系统接口**:Qt DBus
|
||||
- **平台**:Linux Ubuntu
|
||||
- **系统接口**:
|
||||
- Linux: Qt DBus
|
||||
- macOS: Foundation Framework (NSDistributedNotificationCenter)
|
||||
- **平台**:Linux Ubuntu / macOS 10.12+
|
||||
|
||||
## 系统要求
|
||||
|
||||
- Linux Ubuntu 18.04 或更高版本(也支持 Deepin OS)
|
||||
- Qt 5.15.2(安装在 `$HOME/sdk/qt-5.15.2`)
|
||||
### Linux
|
||||
- Linux Ubuntu 18.04 或更高版本(也支持 Deepin OS、Fedora 等)
|
||||
- Qt 5.15.2 或更高版本
|
||||
- CMake 3.10 或更高版本
|
||||
- GCC/G++ 编译器(支持 C++11)
|
||||
- DBus 系统服务
|
||||
|
||||
### macOS
|
||||
- macOS 10.12 (Sierra) 或更高版本
|
||||
- Qt 5.15.2 或更高版本(可通过 Homebrew 安装)
|
||||
- CMake 3.10 或更高版本
|
||||
- Xcode Command Line Tools
|
||||
- Foundation 和 Cocoa 框架(系统自带)
|
||||
|
||||
## 安装与编译
|
||||
|
||||
### 1. 确保 Qt5 已安装
|
||||
### macOS 平台
|
||||
|
||||
#### 1. 安装依赖
|
||||
|
||||
使用 Homebrew 安装 Qt5:
|
||||
|
||||
```bash
|
||||
# 检查 Qt5 目录是否存在
|
||||
# 安装 Homebrew(如果尚未安装)
|
||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||||
|
||||
# 安装 Qt5
|
||||
brew install qt@5
|
||||
|
||||
# 安装 CMake(如果尚未安装)
|
||||
brew install cmake
|
||||
```
|
||||
|
||||
或者从 Qt 官网下载安装器:https://www.qt.io/download
|
||||
|
||||
#### 2. 编译项目
|
||||
|
||||
```bash
|
||||
# 赋予脚本执行权限
|
||||
chmod +x build_mac.sh run_mac.sh
|
||||
|
||||
# 编译
|
||||
./build_mac.sh
|
||||
```
|
||||
|
||||
脚本会自动搜索 Qt 安装路径。如果需要手动指定,可以设置环境变量:
|
||||
|
||||
```bash
|
||||
export Qt5_DIR=/path/to/qt/lib/cmake/Qt5
|
||||
./build_mac.sh
|
||||
```
|
||||
|
||||
### Linux 平台
|
||||
|
||||
#### 1. 确保 Qt5 已安装
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install qt5-default qtbase5-dev libqt5dbus5
|
||||
|
||||
# Fedora
|
||||
sudo dnf install qt5-qtbase-devel qt5-qtbase-gui
|
||||
|
||||
# 或使用自定义安装的 Qt
|
||||
ls $HOME/sdk/qt-5.15.2
|
||||
```
|
||||
|
||||
如果 Qt5 安装在其他位置,请修改 `CMakeLists.txt` 中的 Qt5_DIR 路径:
|
||||
如果 Qt5 安装在其他位置,请修改 `CMakeLists.txt` 中的 Qt5_DIR 路径或设置环境变量。
|
||||
|
||||
```cmake
|
||||
set(Qt5_DIR "$ENV{HOME}/sdk/qt-5.15.2/lib/cmake/Qt5")
|
||||
```
|
||||
|
||||
### 2. 赋予脚本执行权限
|
||||
#### 2. 赋予脚本执行权限
|
||||
|
||||
```bash
|
||||
chmod +x build.sh run.sh
|
||||
```
|
||||
|
||||
### 3. 编译项目
|
||||
#### 3. 编译项目
|
||||
|
||||
```bash
|
||||
./build.sh
|
||||
```
|
||||
|
||||
编译成功后,可执行文件将生成在 `build/bin/ScreenLockDemo`
|
||||
编译成功后,可执行文件将生成在 `build/bin/ScreenLockDetector`
|
||||
|
||||
## 运行应用
|
||||
|
||||
### 方法 1:使用运行脚本(推荐)
|
||||
### macOS 平台
|
||||
|
||||
#### 方法 1:使用运行脚本(推荐)
|
||||
|
||||
```bash
|
||||
./run_mac.sh
|
||||
```
|
||||
|
||||
#### 方法 2:直接运行可执行文件
|
||||
|
||||
```bash
|
||||
./build/bin/ScreenLockDetector
|
||||
```
|
||||
|
||||
#### 方法 3:手动设置环境变量并运行
|
||||
|
||||
```bash
|
||||
export DYLD_LIBRARY_PATH=/path/to/qt/lib:$DYLD_LIBRARY_PATH
|
||||
./build/bin/ScreenLockDetector
|
||||
```
|
||||
|
||||
### Linux 平台
|
||||
|
||||
#### 方法 1:使用运行脚本(推荐)
|
||||
|
||||
```bash
|
||||
./run.sh
|
||||
```
|
||||
|
||||
### 方法 2:直接运行可执行文件
|
||||
#### 方法 2:直接运行可执行文件
|
||||
|
||||
```bash
|
||||
cd build/bin
|
||||
./ScreenLockDemo
|
||||
./ScreenLockDetector
|
||||
```
|
||||
|
||||
### 方法 3:手动设置环境变量并运行
|
||||
#### 方法 3:手动设置环境变量并运行
|
||||
|
||||
```bash
|
||||
export LD_LIBRARY_PATH=$HOME/sdk/qt-5.15.2/lib:$LD_LIBRARY_PATH
|
||||
./build/bin/ScreenLockDemo
|
||||
./build/bin/ScreenLockDetector
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
|
@ -103,7 +186,8 @@ export LD_LIBRARY_PATH=$HOME/sdk/qt-5.15.2/lib:$LD_LIBRARY_PATH
|
|||
1. **启动应用**:运行应用后,会看到一个带有动态动画的窗口
|
||||
|
||||
2. **测试锁屏检测**:
|
||||
- 使用快捷键锁定屏幕:`Ctrl + Alt + L` 或 `Super + L`
|
||||
- **macOS**: 使用快捷键 `Ctrl + Cmd + Q` 或从菜单栏选择"锁定屏幕"
|
||||
- **Linux**: 使用快捷键 `Ctrl + Alt + L` 或 `Super + L`
|
||||
- 观察动画是否停止
|
||||
- 解锁后动画应自动恢复
|
||||
|
||||
|
|
@ -120,7 +204,7 @@ export LD_LIBRARY_PATH=$HOME/sdk/qt-5.15.2/lib:$LD_LIBRARY_PATH
|
|||
|
||||
## 工作原理
|
||||
|
||||
### DBus 监听机制
|
||||
### Linux: DBus 监听机制
|
||||
|
||||
应用程序通过 Qt DBus 连接到 Linux 系统的锁屏服务:
|
||||
|
||||
|
|
@ -148,6 +232,29 @@ export LD_LIBRARY_PATH=$HOME/sdk/qt-5.15.2/lib:$LD_LIBRARY_PATH
|
|||
Signals: Lock(), Unlock()
|
||||
```
|
||||
|
||||
### macOS: 分布式通知中心
|
||||
|
||||
应用程序通过 NSDistributedNotificationCenter 监听 macOS 系统通知:
|
||||
|
||||
1. **屏幕锁定通知**
|
||||
```
|
||||
Notification: com.apple.screenIsLocked
|
||||
当用户锁定屏幕时发送
|
||||
```
|
||||
|
||||
2. **屏幕解锁通知**
|
||||
```
|
||||
Notification: com.apple.screenIsUnlocked
|
||||
当用户解锁屏幕时发送
|
||||
```
|
||||
|
||||
3. **屏幕保护程序通知**(辅助检测)
|
||||
```
|
||||
Notifications:
|
||||
- com.apple.screensaver.didstart
|
||||
- com.apple.screensaver.didstop
|
||||
```
|
||||
|
||||
### Paint 事件控制
|
||||
|
||||
当检测到锁屏时:
|
||||
|
|
@ -165,24 +272,72 @@ export LD_LIBRARY_PATH=$HOME/sdk/qt-5.15.2/lib:$LD_LIBRARY_PATH
|
|||
## 项目结构
|
||||
|
||||
```
|
||||
qt_screan_lock/
|
||||
├── CMakeLists.txt # CMake 构建配置
|
||||
ScreenLockDetector/
|
||||
├── CMakeLists.txt # CMake 构建配置(跨平台)
|
||||
├── README.md # 项目文档
|
||||
├── build.sh # 编译脚本
|
||||
├── run.sh # 运行脚本
|
||||
├── build.sh # Linux 编译脚本
|
||||
├── run.sh # Linux 运行脚本
|
||||
├── build_mac.sh # macOS 编译脚本
|
||||
├── run_mac.sh # macOS 运行脚本
|
||||
└── src/
|
||||
├── main.cpp # 程序入口
|
||||
├── mainwindow.h # 主窗口头文件
|
||||
├── mainwindow.cpp # 主窗口实现
|
||||
├── screenlockdetector.h # 锁屏检测器头文件
|
||||
├── screenlockdetector.cpp # 锁屏检测器实现
|
||||
├── customwidget.h # 自定义组件头文件
|
||||
└── customwidget.cpp # 自定义组件实现
|
||||
├── main.cpp # 程序入口
|
||||
├── mainwindow.h # 主窗口头文件
|
||||
├── mainwindow.cpp # 主窗口实现
|
||||
├── screenlockdetector.h # 跨平台锁屏检测器头文件
|
||||
├── screenlockdetector.cpp # 跨平台锁屏检测器实现
|
||||
├── screenlockdetector_mac.h # macOS 特定实现头文件
|
||||
├── screenlockdetector_mac.mm # macOS 特定实现(Objective-C++)
|
||||
├── customwidget.h # 自定义组件头文件
|
||||
└── customwidget.cpp # 自定义组件实现
|
||||
```
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 问题 1:锁屏检测不工作
|
||||
### macOS 平台
|
||||
|
||||
#### 问题 1:应用无法检测到锁屏
|
||||
|
||||
**可能原因**:
|
||||
- 权限问题
|
||||
- 系统通知未正常工作
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 查看应用日志
|
||||
./run_mac.sh 2>&1 | grep "ScreenLock"
|
||||
|
||||
# 检查系统完整性保护(SIP)状态
|
||||
csrutil status
|
||||
|
||||
# 确保应用有必要的权限
|
||||
```
|
||||
|
||||
#### 问题 2:编译错误 - Qt5 not found
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 使用 Homebrew 安装 Qt5
|
||||
brew install qt@5
|
||||
|
||||
# 设置 Qt5_DIR 环境变量
|
||||
export Qt5_DIR=$(brew --prefix qt@5)/lib/cmake/Qt5
|
||||
./build_mac.sh
|
||||
```
|
||||
|
||||
#### 问题 3:运行时找不到 Qt 库
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 设置 DYLD_LIBRARY_PATH
|
||||
export DYLD_LIBRARY_PATH=$(brew --prefix qt@5)/lib:$DYLD_LIBRARY_PATH
|
||||
|
||||
# 或使用 run_mac.sh 脚本(已包含此配置)
|
||||
./run_mac.sh
|
||||
```
|
||||
|
||||
### Linux 平台
|
||||
|
||||
#### 问题 1:锁屏检测不工作
|
||||
|
||||
**可能原因**:
|
||||
- DBus 服务未运行
|
||||
|
|
@ -272,6 +427,13 @@ Qt Screen Lock Detection Demo
|
|||
|
||||
## 更新日志
|
||||
|
||||
### v2.0.0 (2024)
|
||||
- ✅ **重大更新**: 新增 macOS 平台支持
|
||||
- ✅ 实现跨平台架构(Linux + macOS)
|
||||
- ✅ macOS: 使用 NSDistributedNotificationCenter 监听系统通知
|
||||
- ✅ 创建平台特定的构建和运行脚本
|
||||
- ✅ 更新文档,包含 macOS 使用说明
|
||||
|
||||
### v1.1.0 (2024)
|
||||
- ✅ 新增 Deepin OS (DDE) 锁屏检测支持
|
||||
- ✅ 优化多桌面环境兼容性
|
||||
|
|
|
|||
16
build.sh
16
build.sh
|
|
@ -17,15 +17,15 @@ echo "========================================"
|
|||
echo ""
|
||||
|
||||
# Check if Qt5 directory exists
|
||||
QT5_DIR="$HOME/sdk/qt-5.15.2"
|
||||
if [ ! -d "$QT5_DIR" ]; then
|
||||
echo -e "${RED}Error: Qt5 directory not found at $QT5_DIR${NC}"
|
||||
echo "Please install Qt5 or update the path in CMakeLists.txt"
|
||||
exit 1
|
||||
fi
|
||||
# QT5_DIR="$HOME/sdk/qt-5.15.2"
|
||||
# if [ ! -d "$QT5_DIR" ]; then
|
||||
# echo -e "${RED}Error: Qt5 directory not found at $QT5_DIR${NC}"
|
||||
# echo "Please install Qt5 or update the path in CMakeLists.txt"
|
||||
# exit 1
|
||||
# fi
|
||||
|
||||
echo -e "${GREEN}✓ Qt5 directory found: $QT5_DIR${NC}"
|
||||
echo ""
|
||||
# echo -e "${GREEN}✓ Qt5 directory found: $QT5_DIR${NC}"
|
||||
# echo ""
|
||||
|
||||
# Create build directory
|
||||
BUILD_DIR="build"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
#!/bin/bash
|
||||
|
||||
# macOS Build Script for ScreenLockDetector
|
||||
# This script builds the project on macOS
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
echo "=========================================="
|
||||
echo "Building ScreenLockDetector for macOS"
|
||||
echo "=========================================="
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if we're on macOS
|
||||
if [[ "$OSTYPE" != "darwin"* ]]; then
|
||||
echo -e "${RED}Error: This script is for macOS only${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to find Qt installation
|
||||
find_qt() {
|
||||
# Try to find Qt in common locations
|
||||
QT_PATHS=(
|
||||
"/opt/local" # MacPorts
|
||||
"/usr/local/opt/qt@5" # Homebrew (Intel)
|
||||
"/opt/homebrew/opt/qt@5" # Homebrew (Apple Silicon)
|
||||
"$HOME/Qt/5.15.2/clang_64" # Official Qt installer
|
||||
"$HOME/sdk/qt-5.15.2" # Custom installation
|
||||
)
|
||||
|
||||
for path in "${QT_PATHS[@]}"; do
|
||||
if [ -d "$path" ]; then
|
||||
# Check if Qt cmake files exist
|
||||
if [ -f "$path/lib/cmake/Qt5/Qt5Config.cmake" ]; then
|
||||
echo "$path"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Find Qt installation
|
||||
echo "Searching for Qt installation..."
|
||||
QT_PATH=$(find_qt)
|
||||
|
||||
if [ -z "$QT_PATH" ]; then
|
||||
echo -e "${YELLOW}Warning: Qt not found in common locations${NC}"
|
||||
echo "Please install Qt 5 using one of these methods:"
|
||||
echo " 1. MacPorts: sudo port install qt5"
|
||||
echo " 2. Homebrew: brew install qt@5"
|
||||
echo " 3. Official installer: https://www.qt.io/download"
|
||||
echo ""
|
||||
echo "Or set Qt5_DIR environment variable manually:"
|
||||
echo " export Qt5_DIR=/path/to/qt/lib/cmake/Qt5"
|
||||
|
||||
# Ask user if they want to continue anyway
|
||||
read -p "Do you want to continue and let CMake search for Qt? (y/n) " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo -e "${GREEN}Found Qt at: $QT_PATH${NC}"
|
||||
export Qt5_DIR="$QT_PATH/lib/cmake/Qt5"
|
||||
fi
|
||||
|
||||
# Create build directory
|
||||
BUILD_DIR="build"
|
||||
if [ -d "$BUILD_DIR" ]; then
|
||||
echo "Cleaning existing build directory..."
|
||||
rm -rf "$BUILD_DIR"
|
||||
fi
|
||||
|
||||
echo "Creating build directory..."
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
# Run CMake
|
||||
echo ""
|
||||
echo "Running CMake configuration..."
|
||||
cd "$BUILD_DIR"
|
||||
|
||||
if [ -n "$Qt5_DIR" ]; then
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release -DQt5_DIR="$Qt5_DIR"
|
||||
else
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
fi
|
||||
|
||||
# Build the project
|
||||
echo ""
|
||||
echo "Building project..."
|
||||
make -j$(sysctl -n hw.ncpu)
|
||||
|
||||
# Check if build succeeded
|
||||
if [ $? -eq 0 ]; then
|
||||
echo ""
|
||||
echo -e "${GREEN}=========================================="
|
||||
echo "Build completed successfully!"
|
||||
echo "==========================================${NC}"
|
||||
echo ""
|
||||
echo "Executable location: $BUILD_DIR/bin/ScreenLockDetector"
|
||||
echo ""
|
||||
echo "To run the application:"
|
||||
echo " ./run_mac.sh"
|
||||
echo " or"
|
||||
echo " ./build/bin/ScreenLockDetector"
|
||||
else
|
||||
echo -e "${RED}=========================================="
|
||||
echo "Build failed!"
|
||||
echo "==========================================${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
#!/bin/bash
|
||||
|
||||
# macOS Run Script for ScreenLockDetector
|
||||
# This script runs the application on macOS
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
echo "=========================================="
|
||||
echo "Running ScreenLockDetector on macOS"
|
||||
echo "=========================================="
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Check if we're on macOS
|
||||
if [[ "$OSTYPE" != "darwin"* ]]; then
|
||||
echo -e "${RED}Error: This script is for macOS only${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if executable exists
|
||||
EXECUTABLE="build/bin/ScreenLockDetector"
|
||||
|
||||
if [ ! -f "$EXECUTABLE" ]; then
|
||||
echo -e "${RED}Error: Executable not found at $EXECUTABLE${NC}"
|
||||
echo ""
|
||||
echo "Please build the project first:"
|
||||
echo " ./build_mac.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Function to find Qt installation
|
||||
find_qt() {
|
||||
# Try to find Qt in common locations
|
||||
QT_PATHS=(
|
||||
"/opt/local" # MacPorts
|
||||
"/usr/local/opt/qt@5" # Homebrew (Intel)
|
||||
"/opt/homebrew/opt/qt@5" # Homebrew (Apple Silicon)
|
||||
"$HOME/Qt/5.15.2/clang_64" # Official Qt installer
|
||||
"$HOME/sdk/qt-5.15.2" # Custom installation
|
||||
)
|
||||
|
||||
for path in "${QT_PATHS[@]}"; do
|
||||
if [ -d "$path" ]; then
|
||||
# Check if Qt cmake files exist
|
||||
if [ -f "$path/lib/cmake/Qt5/Qt5Config.cmake" ]; then
|
||||
echo "$path"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
# Find Qt installation and set up library path
|
||||
QT_PATH=$(find_qt)
|
||||
|
||||
if [ -n "$QT_PATH" ]; then
|
||||
echo -e "${GREEN}Found Qt at: $QT_PATH${NC}"
|
||||
export DYLD_LIBRARY_PATH="$QT_PATH/lib:$DYLD_LIBRARY_PATH"
|
||||
export DYLD_FRAMEWORK_PATH="$QT_PATH/lib:$DYLD_FRAMEWORK_PATH"
|
||||
else
|
||||
echo -e "${YELLOW}Warning: Qt not found in common locations${NC}"
|
||||
echo "If the application fails to run, please set DYLD_LIBRARY_PATH manually:"
|
||||
echo " export DYLD_LIBRARY_PATH=/path/to/qt/lib:\$DYLD_LIBRARY_PATH"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Run the application
|
||||
echo ""
|
||||
echo "Starting ScreenLockDetector..."
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
./"$EXECUTABLE"
|
||||
|
||||
echo ""
|
||||
echo "Application exited."
|
||||
|
|
@ -1,23 +1,36 @@
|
|||
#include "screenlockdetector.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "screenlockdetector_mac.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QDBusMessage>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#include <QDBusReply>
|
||||
#endif
|
||||
|
||||
ScreenLockDetector::ScreenLockDetector(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_isLocked(false)
|
||||
#ifdef Q_OS_LINUX
|
||||
, m_gnomeInterface(nullptr)
|
||||
, m_loginInterface(nullptr)
|
||||
, m_deepinInterface(nullptr)
|
||||
, m_gnomeConnected(false)
|
||||
, m_loginConnected(false)
|
||||
, m_deepinConnected(false)
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
, m_macDetector(nullptr)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
ScreenLockDetector::~ScreenLockDetector()
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
if (m_gnomeInterface) {
|
||||
delete m_gnomeInterface;
|
||||
m_gnomeInterface = nullptr;
|
||||
|
|
@ -32,6 +45,14 @@ ScreenLockDetector::~ScreenLockDetector()
|
|||
delete m_deepinInterface;
|
||||
m_deepinInterface = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
if (m_macDetector) {
|
||||
delete m_macDetector;
|
||||
m_macDetector = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ScreenLockDetector::isScreenLocked() const
|
||||
|
|
@ -41,8 +62,40 @@ bool ScreenLockDetector::isScreenLocked() const
|
|||
|
||||
bool ScreenLockDetector::initialize()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "Initializing ScreenLockDetector...";
|
||||
qDebug() << "Initializing ScreenLockDetector for macOS...";
|
||||
qDebug() << "=================================================";
|
||||
|
||||
// 创建 macOS 特定的检测器
|
||||
m_macDetector = new ScreenLockDetectorMac(this);
|
||||
|
||||
// 连接信号
|
||||
connect(m_macDetector, &ScreenLockDetectorMac::screenLocked,
|
||||
this, &ScreenLockDetector::screenLocked);
|
||||
connect(m_macDetector, &ScreenLockDetectorMac::screenUnlocked,
|
||||
this, &ScreenLockDetector::screenUnlocked);
|
||||
connect(m_macDetector, &ScreenLockDetectorMac::lockStateChanged,
|
||||
this, [this](bool locked) {
|
||||
m_isLocked = locked;
|
||||
emit lockStateChanged(locked);
|
||||
});
|
||||
|
||||
bool success = m_macDetector->initialize();
|
||||
|
||||
if (success) {
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "ScreenLockDetector initialized successfully on macOS";
|
||||
qDebug() << "=================================================";
|
||||
} else {
|
||||
qWarning() << "Failed to initialize ScreenLockDetector on macOS";
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
#elif defined(Q_OS_LINUX)
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "Initializing ScreenLockDetector for Linux...";
|
||||
qDebug() << "=================================================";
|
||||
|
||||
// 尝试连接到不同的DBus接口
|
||||
|
|
@ -60,13 +113,18 @@ bool ScreenLockDetector::initialize()
|
|||
queryCurrentLockState();
|
||||
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "ScreenLockDetector initialized successfully";
|
||||
qDebug() << "ScreenLockDetector initialized successfully on Linux";
|
||||
qDebug() << "Deepin DDE connected:" << m_deepinConnected;
|
||||
qDebug() << "GNOME ScreenSaver connected:" << m_gnomeConnected;
|
||||
qDebug() << "Login Manager connected:" << m_loginConnected;
|
||||
qDebug() << "=================================================";
|
||||
|
||||
return true;
|
||||
|
||||
#else
|
||||
qWarning() << "ScreenLockDetector: Unsupported platform";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ScreenLockDetector::setLockState(bool locked)
|
||||
|
|
@ -88,6 +146,8 @@ void ScreenLockDetector::setLockState(bool locked)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
|
||||
bool ScreenLockDetector::connectToGnomeScreenSaver()
|
||||
{
|
||||
qDebug() << "\n--- Connecting to GNOME ScreenSaver ---";
|
||||
|
|
@ -451,3 +511,5 @@ void ScreenLockDetector::onSessionUnlocked()
|
|||
qDebug() << "##################################################";
|
||||
setLockState(false);
|
||||
}
|
||||
|
||||
#endif // Q_OS_LINUX
|
||||
|
|
@ -2,20 +2,34 @@
|
|||
#define SCREENLOCKDETECTOR_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QDBusReply>
|
||||
#include <QDBusContext>
|
||||
#include <QCoreApplication>
|
||||
#endif
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
// 前向声明
|
||||
#ifdef Q_OS_MAC
|
||||
class ScreenLockDetectorMac;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 屏幕锁定检测器类
|
||||
* @brief 跨平台屏幕锁定检测器类
|
||||
*
|
||||
* 通过监听Linux系统的DBus信号来检测屏幕锁定/解锁状态
|
||||
* 支持多种桌面环境:Deepin DDE, GNOME, KDE, XFCE等
|
||||
* Linux: 通过监听DBus信号来检测屏幕锁定/解锁状态
|
||||
* 支持多种桌面环境:Deepin DDE, GNOME, KDE, XFCE等
|
||||
*
|
||||
* macOS: 通过监听NSDistributedNotificationCenter的系统通知
|
||||
*/
|
||||
class ScreenLockDetector : public QObject, protected QDBusContext
|
||||
class ScreenLockDetector : public QObject
|
||||
#ifdef Q_OS_LINUX
|
||||
, protected QDBusContext
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
|
@ -30,7 +44,7 @@ public:
|
|||
bool isScreenLocked() const;
|
||||
|
||||
/**
|
||||
* @brief 初始化DBus连接
|
||||
* @brief 初始化平台特定的锁屏检测
|
||||
* @return true 如果初始化成功,否则返回 false
|
||||
*/
|
||||
bool initialize();
|
||||
|
|
@ -54,6 +68,7 @@ signals:
|
|||
*/
|
||||
void lockStateChanged(bool locked);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
private slots:
|
||||
/**
|
||||
* @brief 处理GNOME屏幕保护程序的DBus信号
|
||||
|
|
@ -63,7 +78,7 @@ private slots:
|
|||
|
||||
/**
|
||||
* @brief 处理DEEPIN屏幕保护程序的DBus信号
|
||||
* @param active 屏幕保护程序是否激活
|
||||
* @param visible 屏幕保护程序是否可见
|
||||
*/
|
||||
void onLockFrontVisible(bool visible);
|
||||
|
||||
|
|
@ -76,6 +91,7 @@ private slots:
|
|||
* @brief 处理登录管理器的会话解锁信号
|
||||
*/
|
||||
void onSessionUnlocked();
|
||||
#endif
|
||||
|
||||
private:
|
||||
/**
|
||||
|
|
@ -84,6 +100,7 @@ private:
|
|||
*/
|
||||
void setLockState(bool locked);
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
/**
|
||||
* @brief 连接到GNOME屏幕保护程序的DBus接口
|
||||
* @return true 如果连接成功
|
||||
|
|
@ -112,15 +129,23 @@ private:
|
|||
* @return 当前会话的路径,如果无法确定则返回空字符串
|
||||
*/
|
||||
QString getCurrentSessionPath();
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool m_isLocked; // 当前锁屏状态
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
QDBusInterface *m_gnomeInterface; // GNOME屏幕保护程序接口
|
||||
QDBusInterface *m_loginInterface; // 登录管理器接口
|
||||
QDBusInterface *m_deepinInterface; // Deepin DDE接口
|
||||
bool m_gnomeConnected; // GNOME接口是否连接成功
|
||||
bool m_loginConnected; // 登录管理器接口是否连接成功
|
||||
bool m_deepinConnected; // Deepin DDE接口是否连接成功
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
ScreenLockDetectorMac *m_macDetector; // macOS 特定的检测器
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SCREENLOCKDETECTOR_H
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
#ifndef SCREENLOCKDETECTOR_MAC_H
|
||||
#define SCREENLOCKDETECTOR_MAC_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
/**
|
||||
* @brief macOS 屏幕锁定检测器类
|
||||
*
|
||||
* 通过监听 macOS 的分布式通知中心来检测屏幕锁定/解锁状态
|
||||
* 使用 NSDistributedNotificationCenter 监听系统通知
|
||||
*/
|
||||
class ScreenLockDetectorMac : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScreenLockDetectorMac(QObject *parent = nullptr);
|
||||
~ScreenLockDetectorMac();
|
||||
|
||||
/**
|
||||
* @brief 获取当前锁屏状态
|
||||
* @return true 如果屏幕已锁定,否则返回 false
|
||||
*/
|
||||
bool isScreenLocked() const;
|
||||
|
||||
/**
|
||||
* @brief 初始化通知监听
|
||||
* @return true 如果初始化成功,否则返回 false
|
||||
*/
|
||||
bool initialize();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief 屏幕锁定信号
|
||||
* 当检测到屏幕被锁定时发出
|
||||
*/
|
||||
void screenLocked();
|
||||
|
||||
/**
|
||||
* @brief 屏幕解锁信号
|
||||
* 当检测到屏幕被解锁时发出
|
||||
*/
|
||||
void screenUnlocked();
|
||||
|
||||
/**
|
||||
* @brief 锁屏状态改变信号
|
||||
* @param locked true表示已锁定,false表示已解锁
|
||||
*/
|
||||
void lockStateChanged(bool locked);
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief 处理屏幕锁定通知的回调
|
||||
*/
|
||||
void handleScreenLocked();
|
||||
|
||||
/**
|
||||
* @brief 处理屏幕解锁通知的回调
|
||||
*/
|
||||
void handleScreenUnlocked();
|
||||
|
||||
/**
|
||||
* @brief 处理屏幕保护程序启动通知的回调
|
||||
*/
|
||||
void handleScreenSaverStarted();
|
||||
|
||||
/**
|
||||
* @brief 处理屏幕保护程序停止通知的回调
|
||||
*/
|
||||
void handleScreenSaverStopped();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 设置锁屏状态
|
||||
* @param locked 新的锁屏状态
|
||||
*/
|
||||
void setLockState(bool locked);
|
||||
|
||||
/**
|
||||
* @brief 注册通知观察者
|
||||
* @return true 如果注册成功
|
||||
*/
|
||||
bool registerNotificationObservers();
|
||||
|
||||
/**
|
||||
* @brief 注销通知观察者
|
||||
*/
|
||||
void unregisterNotificationObservers();
|
||||
|
||||
private:
|
||||
bool m_isLocked; // 当前锁屏状态
|
||||
void *m_observerToken; // Objective-C 观察者令牌(不透明指针)
|
||||
bool m_initialized; // 是否已初始化
|
||||
};
|
||||
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
#endif // SCREENLOCKDETECTOR_MAC_H
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
#include "screenlockdetector_mac.h"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <QDebug>
|
||||
|
||||
// Objective-C 观察者类,用于接收通知
|
||||
@interface ScreenLockObserver : NSObject
|
||||
@property (nonatomic, assign) ScreenLockDetectorMac *detector;
|
||||
- (instancetype)initWithDetector:(ScreenLockDetectorMac *)detector;
|
||||
- (void)screenLocked:(NSNotification *)notification;
|
||||
- (void)screenUnlocked:(NSNotification *)notification;
|
||||
- (void)screenSaverStarted:(NSNotification *)notification;
|
||||
- (void)screenSaverStopped:(NSNotification *)notification;
|
||||
@end
|
||||
|
||||
@implementation ScreenLockObserver
|
||||
|
||||
- (instancetype)initWithDetector:(ScreenLockDetectorMac *)detector
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_detector = detector;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)screenLocked:(NSNotification *)notification
|
||||
{
|
||||
NSLog(@"[ScreenLockObserver] Screen locked notification received");
|
||||
if (_detector) {
|
||||
_detector->handleScreenLocked();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)screenUnlocked:(NSNotification *)notification
|
||||
{
|
||||
NSLog(@"[ScreenLockObserver] Screen unlocked notification received");
|
||||
if (_detector) {
|
||||
_detector->handleScreenUnlocked();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)screenSaverStarted:(NSNotification *)notification
|
||||
{
|
||||
NSLog(@"[ScreenLockObserver] Screen saver started notification received");
|
||||
if (_detector) {
|
||||
_detector->handleScreenSaverStarted();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)screenSaverStopped:(NSNotification *)notification
|
||||
{
|
||||
NSLog(@"[ScreenLockObserver] Screen saver stopped notification received");
|
||||
if (_detector) {
|
||||
_detector->handleScreenSaverStopped();
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
ScreenLockDetectorMac::ScreenLockDetectorMac(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_isLocked(false)
|
||||
, m_observerToken(nullptr)
|
||||
, m_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
ScreenLockDetectorMac::~ScreenLockDetectorMac()
|
||||
{
|
||||
unregisterNotificationObservers();
|
||||
}
|
||||
|
||||
bool ScreenLockDetectorMac::isScreenLocked() const
|
||||
{
|
||||
return m_isLocked;
|
||||
}
|
||||
|
||||
bool ScreenLockDetectorMac::initialize()
|
||||
{
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "Initializing ScreenLockDetectorMac...";
|
||||
qDebug() << "=================================================";
|
||||
|
||||
if (m_initialized) {
|
||||
qWarning() << "ScreenLockDetectorMac already initialized";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool success = registerNotificationObservers();
|
||||
|
||||
if (success) {
|
||||
m_initialized = true;
|
||||
qDebug() << "=================================================";
|
||||
qDebug() << "ScreenLockDetectorMac initialized successfully";
|
||||
qDebug() << "Listening for macOS screen lock notifications";
|
||||
qDebug() << "=================================================";
|
||||
} else {
|
||||
qWarning() << "Failed to initialize ScreenLockDetectorMac";
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ScreenLockDetectorMac::registerNotificationObservers()
|
||||
{
|
||||
@autoreleasepool {
|
||||
qDebug() << "\n--- Registering macOS notification observers ---";
|
||||
|
||||
// 创建观察者对象
|
||||
ScreenLockObserver *observer = [[ScreenLockObserver alloc] initWithDetector:this];
|
||||
// 使用 CFBridgingRetain 保持对象,并保存指针
|
||||
m_observerToken = (void *)CFBridgingRetain(observer);
|
||||
|
||||
// 获取分布式通知中心
|
||||
NSDistributedNotificationCenter *center = [NSDistributedNotificationCenter defaultCenter];
|
||||
|
||||
// 注册屏幕锁定通知
|
||||
// macOS 使用 "com.apple.screenIsLocked" 通知
|
||||
[center addObserver:observer
|
||||
selector:@selector(screenLocked:)
|
||||
name:@"com.apple.screenIsLocked"
|
||||
object:nil
|
||||
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
|
||||
|
||||
qDebug() << "Registered observer for: com.apple.screenIsLocked";
|
||||
|
||||
// 注册屏幕解锁通知
|
||||
// macOS 使用 "com.apple.screenIsUnlocked" 通知
|
||||
[center addObserver:observer
|
||||
selector:@selector(screenUnlocked:)
|
||||
name:@"com.apple.screenIsUnlocked"
|
||||
object:nil
|
||||
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
|
||||
|
||||
qDebug() << "Registered observer for: com.apple.screenIsUnlocked";
|
||||
|
||||
// 注册屏幕保护程序启动通知(可选,作为备用检测方式)
|
||||
[center addObserver:observer
|
||||
selector:@selector(screenSaverStarted:)
|
||||
name:@"com.apple.screensaver.didstart"
|
||||
object:nil
|
||||
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
|
||||
|
||||
qDebug() << "Registered observer for: com.apple.screensaver.didstart";
|
||||
|
||||
// 注册屏幕保护程序停止通知(可选,作为备用检测方式)
|
||||
[center addObserver:observer
|
||||
selector:@selector(screenSaverStopped:)
|
||||
name:@"com.apple.screensaver.didstop"
|
||||
object:nil
|
||||
suspensionBehavior:NSNotificationSuspensionBehaviorDeliverImmediately];
|
||||
|
||||
qDebug() << "Registered observer for: com.apple.screensaver.didstop";
|
||||
|
||||
qDebug() << "Successfully registered all notification observers";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::unregisterNotificationObservers()
|
||||
{
|
||||
@autoreleasepool {
|
||||
if (m_observerToken) {
|
||||
qDebug() << "Unregistering macOS notification observers";
|
||||
|
||||
// 使用 CFBridgingRelease 释放对象
|
||||
ScreenLockObserver *observer = (ScreenLockObserver *)CFBridgingRelease(m_observerToken);
|
||||
NSDistributedNotificationCenter *center = [NSDistributedNotificationCenter defaultCenter];
|
||||
|
||||
// 移除所有通知观察者
|
||||
[center removeObserver:observer];
|
||||
|
||||
m_observerToken = nullptr;
|
||||
m_initialized = false;
|
||||
|
||||
qDebug() << "Notification observers unregistered";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::setLockState(bool locked)
|
||||
{
|
||||
if (m_isLocked != locked) {
|
||||
m_isLocked = locked;
|
||||
|
||||
qDebug() << "##################################################";
|
||||
qDebug() << "## Screen lock state changed:" << (locked ? "LOCKED" : "UNLOCKED");
|
||||
qDebug() << "##################################################";
|
||||
|
||||
emit lockStateChanged(locked);
|
||||
|
||||
if (locked) {
|
||||
emit screenLocked();
|
||||
} else {
|
||||
emit screenUnlocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::handleScreenLocked()
|
||||
{
|
||||
qDebug() << "##################################################";
|
||||
qDebug() << "## macOS LOCK NOTIFICATION RECEIVED";
|
||||
qDebug() << "## Screen is now LOCKED";
|
||||
qDebug() << "##################################################";
|
||||
setLockState(true);
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::handleScreenUnlocked()
|
||||
{
|
||||
qDebug() << "##################################################";
|
||||
qDebug() << "## macOS UNLOCK NOTIFICATION RECEIVED";
|
||||
qDebug() << "## Screen is now UNLOCKED";
|
||||
qDebug() << "##################################################";
|
||||
setLockState(false);
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::handleScreenSaverStarted()
|
||||
{
|
||||
qDebug() << "##################################################";
|
||||
qDebug() << "## macOS SCREEN SAVER STARTED";
|
||||
qDebug() << "## Note: Screen saver started (may not be locked yet)";
|
||||
qDebug() << "##################################################";
|
||||
// 屏幕保护程序启动不一定意味着锁定
|
||||
// 只有在设置中启用了"从睡眠或屏幕保护程序恢复时需要密码"时才会锁定
|
||||
// 我们可以选择在这里设置锁定状态,或者等待真正的锁定通知
|
||||
// 为了保守起见,这里不设置锁定状态
|
||||
}
|
||||
|
||||
void ScreenLockDetectorMac::handleScreenSaverStopped()
|
||||
{
|
||||
qDebug() << "##################################################";
|
||||
qDebug() << "## macOS SCREEN SAVER STOPPED";
|
||||
qDebug() << "## Note: Screen saver stopped";
|
||||
qDebug() << "##################################################";
|
||||
// 屏幕保护程序停止,但解锁通知会单独发送
|
||||
}
|
||||
|
||||
#endif // Q_OS_MAC
|
||||
Loading…
Reference in New Issue