1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
// license:BSD-3-Clause
// copyright-holders: Brad Hughes, Aaron Giles
/*
* monitor_win32.cpp
*
*/
#include "modules/osdmodule.h"
#include "monitor_module.h"
#if defined(OSD_WINDOWS)
// standard windows headers
#include <windows.h>
#undef interface
#include "strconv.h"
#include "windows/video.h"
#include "window.h"
#include "monitor_common.h"
class win32_monitor_module;
class win32_monitor_info : public osd_monitor_info
{
private:
MONITORINFOEX m_info;
public:
win32_monitor_info(monitor_module& module, const HMONITOR handle, const char* monitor_device, float aspect)
: osd_monitor_info(module, std::uintptr_t(handle), monitor_device, aspect)
{
win32_monitor_info::refresh();
}
void refresh() override
{
BOOL result;
// fetch the latest info about the monitor
m_info.cbSize = sizeof(m_info);
result = GetMonitorInfo(reinterpret_cast<HMONITOR>(oshandle()), static_cast<LPMONITORINFO>(&m_info));
assert(result);
m_name = osd::text::from_tstring(m_info.szDevice);
m_pos_size = RECT_to_osd_rect(m_info.rcMonitor);
m_usuable_pos_size = RECT_to_osd_rect(m_info.rcWork);
m_is_primary = ((m_info.dwFlags & MONITORINFOF_PRIMARY) != 0);
(void)result; // to silence gcc 4.6
}
};
class win32_monitor_module : public monitor_module_base
{
public:
win32_monitor_module()
: monitor_module_base(OSD_MONITOR_PROVIDER, "win32")
{
}
std::shared_ptr<osd_monitor_info> monitor_from_rect(const osd_rect& rect) override
{
if (!m_initialized)
return nullptr;
RECT p;
p.top = rect.top();
p.left = rect.left();
p.bottom = rect.bottom();
p.right = rect.right();
auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromRect(&p, MONITOR_DEFAULTTONEAREST)));
assert(nearest != nullptr);
return nearest;
}
std::shared_ptr<osd_monitor_info> monitor_from_window(const osd_window& window) override
{
if (!m_initialized)
return nullptr;
auto nearest = monitor_from_handle(reinterpret_cast<std::uintptr_t>(MonitorFromWindow(static_cast<const win_window_info &>(window).platform_window(), MONITOR_DEFAULTTONEAREST)));
assert(nearest != nullptr);
return nearest;
}
protected:
int init_internal(const osd_options& options) override
{
// make a list of monitors
EnumDisplayMonitors(nullptr, nullptr, monitor_enum_callback, reinterpret_cast<std::intptr_t>(this));
// if we're verbose, print the list of monitors
{
for (auto monitor : list())
{
osd_printf_verbose("Video: Monitor %I64u = \"%s\" %s\n", monitor->oshandle(), monitor->devicename().c_str(), monitor->is_primary() ? "(primary)" : "");
}
}
return 0;
}
private:
static BOOL CALLBACK monitor_enum_callback(HMONITOR handle, HDC dc, LPRECT rect, LPARAM data)
{
win32_monitor_module* self = reinterpret_cast<win32_monitor_module*>(data);
MONITORINFOEX info;
BOOL result;
// get the monitor info
info.cbSize = sizeof(info);
result = GetMonitorInfo(handle, static_cast<LPMONITORINFO>(&info));
assert(result);
(void)result; // to silence gcc 4.6
// guess the aspect ratio assuming square pixels
float aspect = static_cast<float>(info.rcMonitor.right - info.rcMonitor.left) / static_cast<float>(info.rcMonitor.bottom - info.rcMonitor.top);
// allocate a new monitor info
auto temp = osd::text::from_tstring(info.szDevice);
// copy in the data
auto monitor = std::make_shared<win32_monitor_info>(*self, handle, temp.c_str(), aspect);
// hook us into the list
self->add_monitor(monitor);
// enumerate all the available monitors so to list their names in verbose mode
return TRUE;
}
};
#else
MODULE_NOT_SUPPORTED(win32_monitor_module, OSD_MONITOR_PROVIDER, "win32")
#endif
MODULE_DEFINITION(MONITOR_WIN32, win32_monitor_module)
|