[vlc-commits] [Git][videolan/vlc][master] 2 commits: vout: win32: keep track of monitor changes

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Sep 24 08:38:04 UTC 2022



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
7cdf2b5f by Niklas Haas at 2022-09-24T08:23:36+00:00
vout: win32: keep track of monitor changes

Boilerplate logic leading up to the next commit.

- - - - -
ee462c83 by Niklas Haas at 2022-09-24T08:23:36+00:00
vout: win32: implement ICC profile reading

The Win32 APIs make this somewhat easy for us but also somewhat hard.
It's easy to associate between monitors and profiles, but unfortunately
only in the form of filenames which we then have to read manually.

- - - - -


2 changed files:

- modules/video_output/Makefile.am
- modules/video_output/win32/window.c


Changes:

=====================================
modules/video_output/Makefile.am
=====================================
@@ -252,6 +252,7 @@ endif
 
 libwin32_window_plugin_la_SOURCES = video_output/win32/window.c \
 	video_output/wasync_resize_compressor.h
+libwin32_window_plugin_la_LIBADD = -lgdi32
 if HAVE_WIN32_DESKTOP
 vout_LTLIBRARIES += libwin32_window_plugin.la
 endif


=====================================
modules/video_output/win32/window.c
=====================================
@@ -33,6 +33,8 @@
 
 #include <vlc_common.h>
 #include <vlc_charset.h>
+#include <vlc_es.h>
+#include <vlc_frame.h>
 #include <vlc_plugin.h>
 #include <vlc_window.h>
 #include <vlc_mouse.h>
@@ -56,9 +58,13 @@ typedef struct vout_window_sys_t
 
     HWND hwnd;
 
+    HMONITOR monitor; /* last monitor associated with window */
     WCHAR class_main[256];
     HICON vlc_icon;
 
+    /* icc profile */
+    char *icc_profile;
+
     /* mouse */
     unsigned button_pressed;
 
@@ -242,6 +248,78 @@ static void MouseReleased( vlc_window_t *wnd, unsigned button )
     vlc_window_ReportMouseReleased(wnd, button);
 }
 
+#define MAX_ICC_FILE_SIZE  (100*1024*1024)
+
+static void UpdateICCProfile(vlc_window_t *wnd, const wchar_t *pathw)
+{
+    vout_window_sys_t *sys = wnd->sys;
+    vlc_icc_profile_t *icc = NULL;
+
+    if (!pathw) {
+        /* Profile cleared */
+        if (sys->icc_profile) {
+            free(sys->icc_profile);
+            sys->icc_profile = NULL;
+            vlc_window_ReportICCProfile(wnd, NULL);
+        }
+        return;
+    }
+
+    char *path = FromWide(pathw);
+    if (!path)
+        goto error;
+
+    if (sys->icc_profile && strcmp(path, sys->icc_profile) == 0) {
+        /* No change to profile */
+        free(path);
+        return;
+    }
+
+    free(sys->icc_profile);
+    sys->icc_profile = path;
+
+    /* Open ICC profile */
+    vlc_frame_t *frame = vlc_frame_FilePath(path, false);
+    if (!frame)
+        goto error;
+    vlc_frame_cleanup_push(frame);
+
+    icc = malloc(sizeof(*icc) + frame->i_buffer);
+    if (!icc)
+        goto error;
+
+    icc->size = frame->i_buffer;
+    memcpy(icc->data, frame->p_buffer, icc->size);
+    /* fall through */
+
+error:
+    if (!icc)
+        msg_Err(wnd, "Failed to open ICC profile: %s", path ? path : "(unknown)");
+
+    vlc_cleanup_pop();
+    vlc_window_ReportICCProfile(wnd, icc);
+}
+
+static void MonitorChanged(vlc_window_t *wnd, HMONITOR monitor)
+{
+    MONITORINFOEXW mi = { .cbSize = sizeof(mi) };
+    GetMonitorInfoW(monitor, (LPMONITORINFO) &mi);
+
+    /* Try updating ICC profile */
+    HDC ic = CreateICW(mi.szDevice, NULL, NULL, NULL);
+    if (!ic)
+        return;
+
+    wchar_t iccw[MAX_PATH];
+    if (GetICMProfileW(ic, &(DWORD){ sizeof(iccw) }, iccw)) {
+        UpdateICCProfile(wnd, iccw);
+    } else {
+        UpdateICCProfile(wnd, NULL);
+    }
+
+    DeleteDC(ic);
+}
+
 
 static struct
 {
@@ -364,6 +442,23 @@ static long FAR PASCAL WinVoutEventProc( HWND hwnd, UINT message,
     case WM_NCMOUSEMOVE:
         break;
 
+    case WM_DISPLAYCHANGE:
+    {
+        vout_window_sys_t *sys = wnd->sys;
+        sys->monitor = NULL;
+    }
+    /* fall through */
+    case WM_MOVE:
+    {
+        vout_window_sys_t *sys = wnd->sys;
+        HMONITOR hmon = MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTONEAREST);
+        if (hmon != sys->monitor) {
+            sys->monitor = hmon;
+            MonitorChanged(wnd, hmon);
+        }
+        break;
+    }
+
     case WM_CAPTURECHANGED:
     {
         vout_window_sys_t *sys = wnd->sys;
@@ -643,6 +738,10 @@ static void *EventThread( void *p_this )
         return NULL;
     }
 
+    /* Detect starting monitor */
+    sys->monitor = MonitorFromWindow(sys->hwnd, MONITOR_DEFAULTTOPRIMARY);
+    MonitorChanged(wnd, sys->monitor);
+
     /* Append a "Always On Top" entry in the system menu */
     HMENU hMenu = GetSystemMenu( sys->hwnd, FALSE );
     AppendMenu( hMenu, MF_SEPARATOR, 0, TEXT("") );



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/bc9b62b7babf97942fc48e89925f7716fe050b8a...ee462c838de769f1c44306975b85c4bab4186baa

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/bc9b62b7babf97942fc48e89925f7716fe050b8a...ee462c838de769f1c44306975b85c4bab4186baa
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list