Skip to content

Commit e740125

Browse files
committed
w32_common: add display-names/friendly property
The `friendly` subkey return the same set of displays as `display-names` but it attempts to convert the names to the human-friendly name that DisplayConfig obtains from the EDID.
1 parent 088d99f commit e740125

File tree

7 files changed

+111
-24
lines changed

7 files changed

+111
-24
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add `display-name/friendly` property on Windows to obtain display names from EDID

DOCS/man/input.rst

+5
Original file line numberDiff line numberDiff line change
@@ -2930,6 +2930,11 @@ Property list
29302930
version >= 4 is used (LVDS-1, HDMI-A-1, X11-1, etc.), or the wl_output model
29312931
reported by the geometry event if protocol version < 4 is used.
29322932

2933+
``display-names/friendly``
2934+
These are the human-friendly names obtained from the monitor EDID
2935+
(Dell AW3223DW, LC34G55T, etc.). These follow the same order as
2936+
``display-names`` (Windows only)
2937+
29332938
``display-fps``
29342939
The refresh rate of the current display. Currently, this is the lowest FPS
29352940
of any display covered by the video, as retrieved by the underlying system

player/command.c

+25-11
Original file line numberDiff line numberDiff line change
@@ -2823,21 +2823,16 @@ static int mp_property_focused(void *ctx, struct m_property *prop,
28232823
return m_property_bool_ro(action, arg, focused);
28242824
}
28252825

2826-
static int mp_property_display_names(void *ctx, struct m_property *prop,
2827-
int action, void *arg)
2826+
static int get_display_names_subkey(struct vo *vo, int action,
2827+
void *arg, enum mp_voctrl voctrl)
28282828
{
2829-
MPContext *mpctx = ctx;
2830-
struct vo *vo = mpctx->video_out;
2831-
if (!vo)
2832-
return M_PROPERTY_UNAVAILABLE;
2833-
28342829
switch (action) {
28352830
case M_PROPERTY_GET_TYPE:
28362831
*(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING_LIST};
28372832
return M_PROPERTY_OK;
28382833
case M_PROPERTY_GET: {
2839-
char** display_names;
2840-
if (vo_control(vo, VOCTRL_GET_DISPLAY_NAMES, &display_names) < 1)
2834+
char **display_names;
2835+
if (vo_control(vo, voctrl, &display_names) < 1)
28412836
return M_PROPERTY_UNAVAILABLE;
28422837

28432838
*(char ***)arg = display_names;
@@ -2847,6 +2842,25 @@ static int mp_property_display_names(void *ctx, struct m_property *prop,
28472842
return M_PROPERTY_NOT_IMPLEMENTED;
28482843
}
28492844

2845+
static int mp_property_display_names(void *ctx, struct m_property *prop,
2846+
int action, void *arg)
2847+
{
2848+
MPContext *mpctx = ctx;
2849+
struct vo *vo = mpctx->video_out;
2850+
if (!vo)
2851+
return M_PROPERTY_UNAVAILABLE;
2852+
2853+
if (action == M_PROPERTY_KEY_ACTION) {
2854+
struct m_property_action_arg *const ka = arg;
2855+
if (strcmp(ka->key, "friendly"))
2856+
return M_PROPERTY_UNKNOWN;
2857+
2858+
return get_display_names_subkey(vo, ka->action, ka->arg,
2859+
VOCTRL_GET_DISPLAY_NAMES_FRIENDLY);
2860+
}
2861+
return get_display_names_subkey(vo, action, arg, VOCTRL_GET_DISPLAY_NAMES);
2862+
}
2863+
28502864
static int mp_property_vo_configured(void *ctx, struct m_property *prop,
28512865
int action, void *arg)
28522866
{
@@ -4511,8 +4525,8 @@ static const char *const *const mp_event_property_change[] = {
45114525
"demuxer-cache-state"),
45124526
E(MP_EVENT_WIN_RESIZE, "current-window-scale", "osd-width", "osd-height",
45134527
"osd-par", "osd-dimensions"),
4514-
E(MP_EVENT_WIN_STATE, "display-names", "display-fps", "display-width",
4515-
"display-height"),
4528+
E(MP_EVENT_WIN_STATE, "display-names", "display-names/friendly", "display-fps",
4529+
"display-width", "display-height"),
45164530
E(MP_EVENT_WIN_STATE2, "display-hidpi-scale"),
45174531
E(MP_EVENT_FOCUS, "focused"),
45184532
E(MP_EVENT_AMBIENT_LIGHTING_CHANGED, "ambient-light"),

video/out/vo.h

+4
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ enum mp_voctrl {
106106
// names for displays the window is on
107107
VOCTRL_GET_DISPLAY_NAMES,
108108

109+
// char *** (NULL terminated array compatible with CONF_TYPE_STRING_LIST)
110+
// human-friendly names for displays the window is on
111+
VOCTRL_GET_DISPLAY_NAMES_FRIENDLY,
112+
109113
// Retrieve window contents. (Normal screenshots use vo_get_current_frame().)
110114
// Deprecated for VOCTRL_SCREENSHOT with corresponding flags.
111115
VOCTRL_SCREENSHOT_WIN, // struct mp_image**

video/out/w32_common.c

+27-13
Original file line numberDiff line numberDiff line change
@@ -2243,8 +2243,23 @@ struct disp_names_data {
22432243
HMONITOR assoc;
22442244
int count;
22452245
char **names;
2246+
bool friendly;
22462247
};
22472248

2249+
static void disp_names_append(HMONITOR mon, struct disp_names_data *data)
2250+
{
2251+
MONITORINFOEXW mi = { .cbSize = sizeof mi };
2252+
if (GetMonitorInfoW(mon, (MONITORINFO*)&mi)) {
2253+
wchar_t *friendly_name = NULL;
2254+
if (data->friendly) {
2255+
friendly_name = mp_w32_displayconfig_get_friendly_name_from_device(mi.szDevice);
2256+
}
2257+
wchar_t *name = friendly_name ? friendly_name : mi.szDevice;
2258+
MP_TARRAY_APPEND(NULL, data->names, data->count, mp_to_utf8(NULL, name));
2259+
talloc_free(friendly_name);
2260+
}
2261+
}
2262+
22482263
static BOOL CALLBACK disp_names_proc(HMONITOR mon, HDC dc, LPRECT r, LPARAM p)
22492264
{
22502265
struct disp_names_data *data = (struct disp_names_data*)p;
@@ -2253,30 +2268,25 @@ static BOOL CALLBACK disp_names_proc(HMONITOR mon, HDC dc, LPRECT r, LPARAM p)
22532268
if (mon == data->assoc)
22542269
return TRUE;
22552270

2256-
MONITORINFOEXW mi = { .cbSize = sizeof mi };
2257-
if (GetMonitorInfoW(mon, (MONITORINFO*)&mi)) {
2258-
MP_TARRAY_APPEND(NULL, data->names, data->count,
2259-
mp_to_utf8(NULL, mi.szDevice));
2260-
}
2271+
disp_names_append(mon, data);
22612272
return TRUE;
22622273
}
22632274

2264-
static char **get_disp_names(struct vo_w32_state *w32)
2275+
static char **get_disp_names(struct vo_w32_state *w32, bool friendly)
22652276
{
22662277
// Get the client area of the window in screen space
22672278
RECT rect = { 0 };
22682279
GetClientRect(w32->window, &rect);
22692280
MapWindowPoints(w32->window, NULL, (POINT*)&rect, 2);
22702281

2271-
struct disp_names_data data = { .assoc = w32->monitor };
2282+
struct disp_names_data data = {
2283+
.assoc = w32->monitor,
2284+
.friendly = friendly,
2285+
};
22722286

22732287
// Make sure the monitor that Windows considers to be associated with the
22742288
// window is first in the list
2275-
MONITORINFOEXW mi = { .cbSize = sizeof mi };
2276-
if (GetMonitorInfoW(data.assoc, (MONITORINFO*)&mi)) {
2277-
MP_TARRAY_APPEND(NULL, data.names, data.count,
2278-
mp_to_utf8(NULL, mi.szDevice));
2279-
}
2289+
disp_names_append(data.assoc, &data);
22802290

22812291
// Get the names of the other monitors that intersect the client rect
22822292
EnumDisplayMonitors(NULL, &rect, disp_names_proc, (LPARAM)&data);
@@ -2300,6 +2310,7 @@ static bool gui_thread_control_supports(int request)
23002310
case VOCTRL_GET_DISPLAY_FPS:
23012311
case VOCTRL_GET_DISPLAY_RES:
23022312
case VOCTRL_GET_DISPLAY_NAMES:
2313+
case VOCTRL_GET_DISPLAY_NAMES_FRIENDLY:
23032314
case VOCTRL_GET_ICC_PROFILE:
23042315
case VOCTRL_GET_FOCUSED:
23052316
case VOCTRL_BEGIN_DRAGGING:
@@ -2447,7 +2458,10 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg)
24472458
((int *)arg)[1] = monrc.bottom - monrc.top;
24482459
return VO_TRUE;
24492460
case VOCTRL_GET_DISPLAY_NAMES:
2450-
*(char ***)arg = get_disp_names(w32);
2461+
*(char ***)arg = get_disp_names(w32, false);
2462+
return VO_TRUE;
2463+
case VOCTRL_GET_DISPLAY_NAMES_FRIENDLY:
2464+
*(char ***)arg = get_disp_names(w32, true);
24512465
return VO_TRUE;
24522466
case VOCTRL_GET_ICC_PROFILE:
24532467
update_display_info(w32);

video/out/win32/displayconfig.c

+43
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,46 @@ wchar_t *mp_w32_displayconfig_get_device_from_friendly_name(
207207
talloc_free(ctx);
208208
return gdi_device_name;
209209
}
210+
211+
wchar_t *mp_w32_displayconfig_get_friendly_name_from_device(
212+
const wchar_t *device)
213+
{
214+
void *ctx = talloc_new(NULL);
215+
wchar_t *monitor_friendly_device_name = NULL;
216+
217+
// Get the current display configuration
218+
UINT32 num_paths;
219+
DISPLAYCONFIG_PATH_INFO *paths;
220+
UINT32 num_modes;
221+
DISPLAYCONFIG_MODE_INFO *modes;
222+
if (get_config(ctx, &num_paths, &paths, &num_modes, &modes))
223+
goto end;
224+
225+
// Get the path for the specified monitor
226+
DISPLAYCONFIG_PATH_INFO *path;
227+
if (!(path = get_path(num_paths, paths, device)))
228+
goto end;
229+
230+
// Get the friendly name from the path
231+
DISPLAYCONFIG_TARGET_DEVICE_NAME target = {
232+
.header = {
233+
.size = sizeof target,
234+
.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME,
235+
.adapterId = path->targetInfo.adapterId,
236+
.id = path->targetInfo.id,
237+
}
238+
};
239+
if (DisplayConfigGetDeviceInfo(&target.header) != ERROR_SUCCESS)
240+
goto end;
241+
242+
if (!target.flags.friendlyNameFromEdid)
243+
goto end;
244+
245+
monitor_friendly_device_name = talloc_memdup(NULL,
246+
target.monitorFriendlyDeviceName,
247+
sizeof(target.monitorFriendlyDeviceName));
248+
249+
end:
250+
talloc_free(ctx);
251+
return monitor_friendly_device_name;
252+
}

video/out/win32/displayconfig.h

+6
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,10 @@ double mp_w32_displayconfig_get_refresh_rate(const wchar_t *device);
3030
wchar_t *mp_w32_displayconfig_get_device_from_friendly_name(
3131
const wchar_t *monitor_friendly_device_name);
3232

33+
// Given a GDI monitor device name, get a friendly monitor device name
34+
// using the DisplayConfig API. Returns NULL on failure.
35+
// The caller is responsible for releasing the result with talloc_free.
36+
wchar_t *mp_w32_displayconfig_get_friendly_name_from_device(
37+
const wchar_t *device);
38+
3339
#endif

0 commit comments

Comments
 (0)