mirror of
https://github.com/gnif/LookingGlass.git
synced 2026-06-07 23:34:25 +00:00
No GPU notifications are not possible before the notification icon is created. Since the helper could start before explorer.exe (and often does on reboot), the notification would fail. This commit adds logic to refer the notification and we send it immediately when successfully creating the notification icon.
221 lines
5.6 KiB
C++
221 lines
5.6 KiB
C++
/**
|
|
* Looking Glass
|
|
* Copyright © 2017-2026 The Looking Glass Authors
|
|
* https://looking-glass.io
|
|
*
|
|
* 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 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* 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, write to the Free Software Foundation, Inc., 59
|
|
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include "CNotifyWindow.h"
|
|
#include "CConfigWindow.h"
|
|
#include <CDebug.h>
|
|
#include <windowsx.h>
|
|
#include <strsafe.h>
|
|
|
|
#define WM_NOTIFY_ICON (WM_USER)
|
|
#define WM_CLEAN_UP_CONFIG (WM_USER+1)
|
|
#define WM_NO_GPU (WM_USER+2)
|
|
|
|
#define ID_MENU_SHOW_LOG 3000
|
|
#define ID_MENU_SHOW_CONFIG 3001
|
|
|
|
ATOM CNotifyWindow::s_atom = 0;
|
|
UINT CNotifyWindow::s_taskbarCreated = 0;
|
|
|
|
bool CNotifyWindow::registerClass()
|
|
{
|
|
s_taskbarCreated = RegisterWindowMessage(L"TaskbarCreated");
|
|
if (!s_taskbarCreated)
|
|
DEBUG_WARN_HR(GetLastError(), "RegisterWindowMessage(TaskbarCreated)");
|
|
|
|
WNDCLASSEX wx = {};
|
|
populateWindowClass(wx);
|
|
wx.lpszClassName = L"LookingGlassIddHelper";
|
|
|
|
s_atom = RegisterClassEx(&wx);
|
|
return s_atom;
|
|
}
|
|
|
|
CNotifyWindow::CNotifyWindow() : m_iconData({ 0 }), m_iconRegistered(false),
|
|
m_noGPUQueued(false), m_menu(CreatePopupMenu()), closeRequested(false)
|
|
{
|
|
CreateWindowEx(0, MAKEINTATOM(s_atom), NULL,
|
|
0, 0, 0, 0, 0, NULL, NULL, hInstance, this);
|
|
|
|
if (m_menu)
|
|
{
|
|
AppendMenu(m_menu, MF_STRING, ID_MENU_SHOW_LOG, L"Open log directory");
|
|
AppendMenu(m_menu, MF_STRING, ID_MENU_SHOW_CONFIG, L"Open configuration");
|
|
}
|
|
}
|
|
|
|
CNotifyWindow::~CNotifyWindow()
|
|
{
|
|
DestroyMenu(m_menu);
|
|
}
|
|
|
|
LRESULT CNotifyWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_NOTIFY_ICON:
|
|
return onNotifyIcon(LOWORD(lParam), HIWORD(lParam), GET_X_LPARAM(wParam), GET_Y_LPARAM(wParam));
|
|
|
|
case WM_CLEAN_UP_CONFIG:
|
|
if (m_config && !m_config->hwnd())
|
|
{
|
|
DEBUG_INFO("Config window closed");
|
|
m_config.reset();
|
|
}
|
|
return 0;
|
|
|
|
case WM_NO_GPU:
|
|
handleNoGPUNotification();
|
|
return 0;
|
|
|
|
default:
|
|
if (s_taskbarCreated && uMsg == s_taskbarCreated)
|
|
{
|
|
registerIcon();
|
|
return 0;
|
|
}
|
|
return CWindow::handleMessage(uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
LRESULT CNotifyWindow::onCreate()
|
|
{
|
|
// Allow explorer to send us this message to register the notification icon.
|
|
ChangeWindowMessageFilterEx(m_hwnd, s_taskbarCreated, MSGFLT_ALLOW, NULL);
|
|
|
|
registerIcon();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CNotifyWindow::onClose()
|
|
{
|
|
if (closeRequested)
|
|
destroy();
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CNotifyWindow::onDestroy()
|
|
{
|
|
Shell_NotifyIcon(NIM_DELETE, &m_iconData);
|
|
return 0;
|
|
}
|
|
|
|
LRESULT CNotifyWindow::onFinal()
|
|
{
|
|
PostQuitMessage(0);
|
|
return CWindow::onFinal();
|
|
}
|
|
|
|
LRESULT CNotifyWindow::onNotifyIcon(UINT uEvent, WORD wIconId, int x, int y)
|
|
{
|
|
switch (uEvent)
|
|
{
|
|
case WM_CONTEXTMENU:
|
|
SetForegroundWindow(m_hwnd);
|
|
switch (TrackPopupMenu(m_menu, TPM_RETURNCMD | TPM_NONOTIFY, x, y, 0, m_hwnd, NULL))
|
|
{
|
|
case ID_MENU_SHOW_LOG:
|
|
ShellExecute(m_hwnd, L"open", g_debug.logDir(), NULL, NULL, SW_NORMAL);
|
|
break;
|
|
case ID_MENU_SHOW_CONFIG:
|
|
DEBUG_INFO("Config window opened");
|
|
m_config.reset(new CConfigWindow());
|
|
m_config->onDestroy([this]() {
|
|
PostMessage(m_hwnd, WM_CLEAN_UP_CONFIG, 0, 0);
|
|
});
|
|
ShowWindow(*m_config, SW_NORMAL);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void CNotifyWindow::registerIcon()
|
|
{
|
|
m_iconData.cbSize = sizeof m_iconData;
|
|
m_iconData.hWnd = m_hwnd;
|
|
m_iconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
|
m_iconData.uCallbackMessage = WM_NOTIFY_ICON;
|
|
m_iconData.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
|
|
m_iconData.uVersion = NOTIFYICON_VERSION_4;
|
|
StringCbCopy(m_iconData.szTip, sizeof m_iconData.szTip, L"Looking Glass (IDD)");
|
|
|
|
if (!Shell_NotifyIcon(NIM_ADD, &m_iconData))
|
|
{
|
|
DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_ADD)");
|
|
return;
|
|
}
|
|
|
|
m_iconRegistered = true;
|
|
if (!Shell_NotifyIcon(NIM_SETVERSION, &m_iconData))
|
|
DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_SETVERSION)");
|
|
|
|
if (m_noGPUQueued)
|
|
{
|
|
m_noGPUQueued = false;
|
|
handleNoGPUNotification();
|
|
}
|
|
}
|
|
|
|
void CNotifyWindow::noGPUNotification()
|
|
{
|
|
if (m_iconRegistered)
|
|
PostMessage(m_hwnd, WM_NO_GPU, 0, 0);
|
|
else
|
|
m_noGPUQueued = true;
|
|
}
|
|
|
|
void CNotifyWindow::handleNoGPUNotification()
|
|
{
|
|
CRegistrySettings settings;
|
|
LSTATUS error = settings.open();
|
|
if (error != ERROR_SUCCESS)
|
|
DEBUG_ERROR_HR(error, "Failed to load settings");
|
|
|
|
auto noGPU = settings.getNoGPU();
|
|
if (noGPU.has_value() && noGPU.value())
|
|
return;
|
|
|
|
NOTIFYICONDATA nid;
|
|
memcpy(&nid, &m_iconData, sizeof nid);
|
|
|
|
nid.uFlags = NIF_INFO;
|
|
nid.dwInfoFlags = NIIF_WARNING;
|
|
StringCbCopy(nid.szInfoTitle, sizeof nid.szInfoTitle, L"No GPU found!");
|
|
StringCbCopy(nid.szInfo, sizeof nid.szInfo,
|
|
L"GPU acceleration will not be available. "
|
|
L"Looking Glass will use software rendering.");
|
|
|
|
if (!Shell_NotifyIcon(NIM_MODIFY, &nid))
|
|
DEBUG_ERROR_HR(GetLastError(), "Shell_NotifyIcon(NIM_MODIFY)");
|
|
}
|
|
|
|
HWND CNotifyWindow::hwndDialog()
|
|
{
|
|
return m_config ? m_config->hwnd() : nullptr;
|
|
}
|
|
|
|
void CNotifyWindow::close()
|
|
{
|
|
closeRequested = true;
|
|
PostMessage(m_hwnd, WM_CLOSE, 0, 0);
|
|
}
|