Solid

windevicemanager.cpp
1/*
2 SPDX-FileCopyrightText: 2013 Patrick von Reth <vonreth@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include "windevicemanager.h"
8#include "winbattery.h"
9#include "winblock.h"
10#include "windevice.h"
11#include "windevicemanager_p.h"
12#include "winprocessor.h"
13#include <solid/deviceinterface.h>
14
15#include <dbt.h>
16
17using namespace Solid::Backends::Win;
18
19Q_GLOBAL_STATIC(SolidWinEventFilter, solidWineventFilter)
20
21SolidWinEventFilter *SolidWinEventFilter::instance()
22{
23 return solidWineventFilter;
24}
25
26SolidWinEventFilter::SolidWinEventFilter()
27 : QObject()
28{
29 wchar_t title[] = L"KDEWinDeviceManager";
30
31 WNDCLASSEX wcex;
32 ZeroMemory(&wcex, sizeof(wcex));
33 wcex.cbSize = sizeof(WNDCLASSEX);
34 wcex.lpfnWndProc = SolidWinEventFilter::WndProc;
35 wcex.hInstance = (HINSTANCE)::GetModuleHandle(NULL);
36 wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
37 wcex.lpszClassName = title;
38 if (RegisterClassEx(&wcex) == 0) {
39 qWarning() << "Failed to initialize KDEWinDeviceManager we will be unable to detect device changes";
40 return;
41 }
42
43 m_windowID = CreateWindow(title, //
44 title,
45 WS_ICONIC,
46 0,
47 0,
48 CW_USEDEFAULT,
49 0,
50 NULL,
51 NULL,
52 wcex.hInstance,
53 NULL);
54 if (m_windowID == NULL) {
55 qWarning() << "Failed to initialize KDEWinDeviceManager we will be unable to detect device changes";
56 return;
57 }
58 ShowWindow(m_windowID, SW_HIDE);
59}
60
61SolidWinEventFilter::~SolidWinEventFilter()
62{
63 PostMessage(m_windowID, WM_CLOSE, 0, 0);
64}
65
66void SolidWinEventFilter::promoteAddedDevice(const QSet<QString> &udi)
67{
68 Q_EMIT deviceAdded(udi);
69}
70
71void SolidWinEventFilter::promoteRemovedDevice(const QSet<QString> &udi)
72{
73 Q_EMIT deviceRemoved(udi);
74}
75
76void SolidWinEventFilter::promotePowerChange()
77{
78 Q_EMIT powerChanged();
79}
80
81LRESULT CALLBACK SolidWinEventFilter::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
82{
83 // some parts of the code are based on http://www.codeproject.com/Articles/119168/Hardware-Change-Detection
84 switch (message) {
85 case WM_DEVICECHANGE: {
86 if ((wParam == DBT_DEVICEARRIVAL) || (wParam == DBT_DEVICEREMOVECOMPLETE)) {
87 DEV_BROADCAST_HDR *header = reinterpret_cast<DEV_BROADCAST_HDR *>(lParam);
88 if (header->dbch_devicetype == DBT_DEVTYP_VOLUME) {
89 DEV_BROADCAST_VOLUME *devNot = reinterpret_cast<DEV_BROADCAST_VOLUME *>(lParam);
90 switch (wParam) {
91 case DBT_DEVICEREMOVECOMPLETE: {
92 QSet<QString> udis = WinBlock::getFromBitMask(devNot->dbcv_unitmask);
93 solidWineventFilter->promoteRemovedDevice(udis);
94 break;
95 }
96 case DBT_DEVICEARRIVAL: {
97 QSet<QString> udis = WinBlock::updateUdiFromBitMask(devNot->dbcv_unitmask);
98 solidWineventFilter->promoteAddedDevice(udis);
99 break;
100 }
101 }
102 break;
103 }
104 }
105 break;
106 }
107 case WM_POWERBROADCAST: {
108 solidWineventFilter->promotePowerChange();
109 break;
110 }
111 case WM_DESTROY: {
112 PostQuitMessage(0);
113 break;
114 }
115 default:
116 return DefWindowProc(hWnd, message, wParam, lParam);
117 }
118 return 0;
119}
120
121WinDeviceManager::WinDeviceManager(QObject *parent)
122 : DeviceManager(parent)
123{
124 connect(solidWineventFilter, SIGNAL(deviceAdded(QSet<QString>)), this, SLOT(slotDeviceAdded(QSet<QString>)));
125 connect(solidWineventFilter, SIGNAL(deviceRemoved(QSet<QString>)), this, SLOT(slotDeviceRemoved(QSet<QString>)));
126
127 // clang-format off
128 m_supportedInterfaces << Solid::DeviceInterface::GenericInterface
129 // << Solid::DeviceInterface::Block
130 << Solid::DeviceInterface::StorageAccess
131 << Solid::DeviceInterface::StorageDrive
132 << Solid::DeviceInterface::OpticalDrive
133 << Solid::DeviceInterface::StorageVolume
134 << Solid::DeviceInterface::OpticalDisc
135 << Solid::DeviceInterface::Processor
136 << Solid::DeviceInterface::Battery;
137 // clang-format on
138
139 updateDeviceList();
140}
141
142WinDeviceManager::~WinDeviceManager()
143{
144}
145
146QString WinDeviceManager::udiPrefix() const
147{
148 return QString();
149}
150
151QSet<Solid::DeviceInterface::Type> Solid::Backends::Win::WinDeviceManager::supportedInterfaces() const
152{
153 return m_supportedInterfaces;
154}
155
156QStringList WinDeviceManager::allDevices()
157{
158 return m_devicesList;
159}
160
161QStringList WinDeviceManager::devicesFromQuery(const QString &parentUdi, Solid::DeviceInterface::Type type)
162{
164 const QStringList deviceList = allDevices();
165 if (!parentUdi.isEmpty()) {
166 for (const QString &udi : deviceList) {
167 WinDevice device(udi);
168 if (device.type() == type && device.parentUdi() == parentUdi) {
169 list << udi;
170 }
171 }
172 } else if (type != Solid::DeviceInterface::Unknown) {
173 for (const QString &udi : deviceList) {
174 WinDevice device(udi);
175 if (device.queryDeviceInterface(type)) {
176 list << udi;
177 }
178 }
179 } else {
180 list << deviceList;
181 }
182 return list;
183}
184
185QObject *Solid::Backends::Win::WinDeviceManager::createDevice(const QString &udi)
186{
187 if (allDevices().contains(udi)) {
188 return new WinDevice(udi);
189 } else {
190 return 0;
191 }
192}
193
194void WinDeviceManager::slotDeviceAdded(const QSet<QString> &udi)
195{
196 const QSet<QString> tmp = udi - m_devices; // don't report devices that are already known(cd drive)
197 m_devices += tmp;
198 m_devicesList = QStringList(m_devices.begin(), m_devices.end());
199 std::sort(m_devicesList.begin(), m_devicesList.end());
200 for (const QString &str : tmp) {
201 Q_EMIT deviceAdded(str);
202 }
203}
204
205void WinDeviceManager::slotDeviceRemoved(const QSet<QString> &udi)
206{
207 m_devices -= udi;
208 m_devicesList = QStringList(m_devices.begin(), m_devices.end());
209 std::sort(m_devicesList.begin(), m_devicesList.end());
210 for (const QString &str : udi) {
212 }
213}
214
215void WinDeviceManager::updateDeviceList()
216{
217 QSet<QString> devices = WinProcessor::getUdis();
218 devices += WinBlock::getUdis();
219 devices += WinBattery::getUdis();
220
221 m_devices = devices;
222 m_devicesList = QStringList(m_devices.begin(), m_devices.end());
223 std::sort(m_devicesList.begin(), m_devicesList.end());
224}
225
226#include "moc_windevicemanager.cpp"
227#include "moc_windevicemanager_p.cpp"
Type
This enum type defines the type of device interface that a Device can have.
void deviceAdded(const QString &udi)
This signal is emitted when a new device appears in the system.
void deviceRemoved(const QString &udi)
This signal is emitted when a device disappears from the system.
KIOCORE_EXPORT QStringList list(const QString &fileClass)
iterator begin()
iterator end()
Q_EMITQ_EMIT
iterator begin()
iterator end()
bool isEmpty() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:47:59 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.