From 3ccdff0828d84ca20095724c4cd68f20bd1cce6a Mon Sep 17 00:00:00 2001 From: impressionyang Date: Thu, 11 Jun 2026 17:14:10 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20CapsLock=20?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=E5=A4=8D=E4=BD=8D=E5=92=8C=E6=89=98=E7=9B=98?= =?UTF-8?q?=E5=9B=BE=E6=A0=87=E9=BB=91=E8=89=B2=E6=96=B9=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 重复复位: onHotkeyDeactivated() 中移除 simulateCapsLock(), 只保留 onRecognitionComplete() 中的复位调用,确保只复位一次。 无音频时也调用 simulateCapsLock() 复位。 2. 托盘图标黑色方块: 移除自定义 QPixmap 绘制(在某些平台/主题下 渲染为黑色方块),改用应用窗口图标 + QStyle::SP_ComputerIcon 回退。 状态变化通过 tooltip 文字指示,不再切换不同颜色的图标。 Co-Authored-By: Claude Opus 4.7 --- src/core/voice_input_service.cpp | 3 +- src/ui/main_window.cpp | 61 +++++--------------------------- src/ui/main_window.h | 3 -- 3 files changed, 10 insertions(+), 57 deletions(-) diff --git a/src/core/voice_input_service.cpp b/src/core/voice_input_service.cpp index d2bf553..56cc1f6 100644 --- a/src/core/voice_input_service.cpp +++ b/src/core/voice_input_service.cpp @@ -186,8 +186,7 @@ void VoiceInputService::onHotkeyDeactivated() { } if (state_ == Recording) { - // 松开 → 先恢复 CapsLock 灯,再开始识别 - simulateCapsLock(); + // 松开 → 开始识别(CapsLock 灯在识别完成后复位,避免重复) state_ = Idle; LOG_DEBUG(kTag, "Recording → Idle (松开转写)"); stopRecordingAndTranscribe(); diff --git a/src/ui/main_window.cpp b/src/ui/main_window.cpp index 0cd8839..428fa5c 100644 --- a/src/ui/main_window.cpp +++ b/src/ui/main_window.cpp @@ -16,10 +16,9 @@ #include #include #include -#include -#include #include #include +#include static const char* const kTag = "MainWindow"; @@ -111,21 +110,6 @@ void MainWindow::setupTrayIcon() { return; } - // 缓存 6 个状态图标,避免每次重建导致 GUI 卡顿 - QIcon recordingIcon(createTrayIcon(QColor("#e74c3c"))); - QIcon recognizingIcon(createTrayIcon(QColor("#f39c12"))); - QIcon waitingIcon(createTrayIcon(QColor("#f1c40f"))); - QIcon readyIcon(createTrayIcon(QColor("#27ae60"))); - QIcon stoppedIcon(createTrayIcon(QColor("#95a5a6"))); - QIcon otherIcon(createTrayIcon(QColor("#3498db"))); - - trayIcons_["recording"] = recordingIcon; - trayIcons_["recognizing"] = recognizingIcon; - trayIcons_["waiting"] = waitingIcon; - trayIcons_["ready"] = readyIcon; - trayIcons_["stopped"] = stoppedIcon; - trayIcons_["other"] = otherIcon; - trayMenu_ = new QMenu(this); auto* showAction = trayMenu_->addAction("显示主窗口"); connect(showAction, &QAction::triggered, this, [this]() { @@ -141,7 +125,11 @@ void MainWindow::setupTrayIcon() { trayIcon_ = new QSystemTrayIcon(this); trayIcon_->setContextMenu(trayMenu_); - trayIcon_->setIcon(readyIcon); + + // 使用应用窗口图标作为托盘图标,避免自定义绘制导致的黑色方块 + trayIcon_->setIcon(windowIcon().isNull() ? + style()->standardIcon(QStyle::SP_ComputerIcon) : + windowIcon()); trayIcon_->setToolTip("Impress Voice Input - 语音输入就绪"); trayIcon_->show(); @@ -158,44 +146,13 @@ void MainWindow::setupTrayIcon() { } void MainWindow::updateTrayIcon(const QString& status) { - if (!trayIcon_ || trayIcons_.isEmpty()) return; + if (!trayIcon_) return; - // 状态映射到缓存图标 - const QIcon* icon = nullptr; - if (status.contains("正在录音")) { - icon = &trayIcons_["recording"]; - } else if (status.contains("正在识别")) { - icon = &trayIcons_["recognizing"]; - } else if (status.contains("等待长按") || status.contains("PreRecording")) { - icon = &trayIcons_["waiting"]; - } else if (status.contains("已启动") || status.contains("就绪")) { - icon = &trayIcons_["ready"]; - } else if (status.contains("已关闭") || status.contains("停止")) { - icon = &trayIcons_["stopped"]; - } else { - icon = &trayIcons_["other"]; - } - - trayIcon_->setIcon(*icon); + // 根据状态设置 tooltip,图标保持统一的应用图标 + // 避免使用自定义 QPixmap(在某些平台/主题下会显示为黑色方块) trayIcon_->setToolTip(QString("Impress Voice Input - %1").arg(status)); } -QPixmap MainWindow::createTrayIcon(const QColor& color) { - const int size = 16; - QImage image(size, size, QImage::Format_ARGB32); - image.fill(Qt::transparent); - - QPainter painter(&image); - painter.setRenderHint(QPainter::Antialiasing); - - painter.setBrush(color); - painter.setPen(Qt::NoPen); - int margin = 1; - painter.drawEllipse(margin, margin, size - 2 * margin, size - 2 * margin); - - return QPixmap::fromImage(image); -} - void MainWindow::setupMenuBar() { // 文件菜单 auto* fileMenu = menuBar()->addMenu("文件"); diff --git a/src/ui/main_window.h b/src/ui/main_window.h index 37f1617..d223126 100644 --- a/src/ui/main_window.h +++ b/src/ui/main_window.h @@ -2,7 +2,6 @@ #include #include -#include #include class QLabel; @@ -42,7 +41,6 @@ private: void setupStatusBar(SenseVoiceEngine* sttEngine); void setupTrayIcon(); void updateTrayIcon(const QString& status); - QPixmap createTrayIcon(const QColor& color); void loadStyleSheet(); void onVoiceInputConfigChanged(); void updateModelStatus(); @@ -58,7 +56,6 @@ private: QLabel* modelStatusLabel_; QSystemTrayIcon* trayIcon_ = nullptr; QMenu* trayMenu_ = nullptr; - QMap trayIcons_; }; } // namespace impress