Support of the mpv option title-bar

This commit is contained in:
stax76
2023-12-22 18:35:07 +01:00
parent 0ef679e00d
commit 3e4ea03437
8 changed files with 78 additions and 126 deletions

View File

@@ -1,8 +1,7 @@
# v7.0.0.5 Beta (2023-??-??) # v7.0.0.5 Beta (2023-??-??)
- Experimental support of the mpv option `title-bar`. - Support of the mpv option `title-bar`.
While development there were 2 memory access violations while shutdown.
- Command line parser fix using list options with `-add` suffix. - Command line parser fix using list options with `-add` suffix.
- Fix video being rendered with black line at the bottom. - Fix video being rendered with black line at the bottom.

View File

@@ -625,6 +625,7 @@ https://mpv.io/manual/master/#window
- [ontop](https://mpv.io/manual/master/#options-ontop) - [ontop](https://mpv.io/manual/master/#options-ontop)
- [screen](https://mpv.io/manual/master/#options-screen) - [screen](https://mpv.io/manual/master/#options-screen)
- [snap-window](https://mpv.io/manual/master/#options-snap-window) - [snap-window](https://mpv.io/manual/master/#options-snap-window)
- [title-bar](https://mpv.io/manual/master/#options-title-bar)
- [title](https://mpv.io/manual/master/#options-title) - [title](https://mpv.io/manual/master/#options-title)
- [window-maximized](https://mpv.io/manual/master/#options-window-maximized) - [window-maximized](https://mpv.io/manual/master/#options-window-maximized)
- [window-minimized](https://mpv.io/manual/master/#options-window-minimized) - [window-minimized](https://mpv.io/manual/master/#options-window-minimized)

View File

@@ -27,33 +27,33 @@ public static class WinApiHelp
} }
} }
public static void AdjustWindowRect(IntPtr hwnd, ref Rect rc, int dpi) public static void AdjustWindowRect(IntPtr hwnd, ref RECT rc, int dpi)
{ {
uint windowStyle = (uint)GetWindowLong(hwnd, -16); // GWL_STYLE uint style = (uint)GetWindowLongPtr(hwnd, -16); // GWL_STYLE
uint windowStyleEx = (uint)GetWindowLong(hwnd, -20); // GWL_EXSTYLE uint styleEx = (uint)GetWindowLongPtr(hwnd, -20); // GWL_EXSTYLE
if (Environment.OSVersion.Version >= WindowsTen1607) if (Environment.OSVersion.Version >= WindowsTen1607)
AdjustWindowRectExForDpi(ref rc, windowStyle, false, windowStyleEx, (uint)dpi); AdjustWindowRectExForDpi(ref rc, style, false, styleEx, (uint)dpi);
else else
Native.WinApi.AdjustWindowRect(ref rc, windowStyle, false); Native.WinApi.AdjustWindowRect(ref rc, style, false);
} }
public static void AddWindowBorders(IntPtr hwnd, ref Rect rc, int dpi, bool changeTop) public static void AddWindowBorders(IntPtr hwnd, ref RECT rc, int dpi, bool changeTop)
{ {
Rect win = rc; RECT win = rc;
AdjustWindowRect(hwnd, ref rc, dpi); AdjustWindowRect(hwnd, ref rc, dpi);
if (changeTop) if (changeTop)
{ {
int top = rc.Top; int top = rc.Top;
top -= rc.Top - win.Top; top -= rc.Top - win.Top;
rc = new Rect(rc.Left, top, rc.Right, rc.Bottom); rc = new RECT(rc.Left, top, rc.Right, rc.Bottom);
} }
} }
public static void SubtractWindowBorders(IntPtr hwnd, ref Rect rc, int dpi, bool changeTop) public static void SubtractWindowBorders(IntPtr hwnd, ref RECT rc, int dpi, bool changeTop)
{ {
Rect r = new Rect(); RECT r = new RECT();
AddWindowBorders(hwnd, ref r, dpi, changeTop); AddWindowBorders(hwnd, ref r, dpi, changeTop);
rc.Left -= r.Left; rc.Left -= r.Left;
rc.Top -= r.Top; rc.Top -= r.Top;
@@ -63,15 +63,15 @@ public static class WinApiHelp
public static int GetTitleBarHeight(IntPtr hwnd, int dpi) public static int GetTitleBarHeight(IntPtr hwnd, int dpi)
{ {
Rect r = new Rect(); RECT rect = new RECT();
AdjustWindowRect(hwnd, ref r, dpi); AdjustWindowRect(hwnd, ref rect, dpi);
return -r.Top; return -rect.Top;
} }
public static Rectangle GetWorkingArea(IntPtr handle, Rectangle workingArea) public static Rectangle GetWorkingArea(IntPtr handle, Rectangle workingArea)
{ {
if (handle != IntPtr.Zero && GetDwmWindowRect(handle, out Rect dwmRect) && if (handle != IntPtr.Zero && GetDwmWindowRect(handle, out RECT dwmRect) &&
GetWindowRect(handle, out Rect rect)) GetWindowRect(handle, out RECT rect))
{ {
int left = workingArea.Left; int left = workingArea.Left;
int top = workingArea.Top; int top = workingArea.Top;
@@ -89,28 +89,12 @@ public static class WinApiHelp
return workingArea; return workingArea;
} }
public static bool GetDwmWindowRect(IntPtr handle, out Rect rect) public static bool GetDwmWindowRect(IntPtr handle, out RECT rect)
{ {
const uint DWMWA_EXTENDED_FRAME_BOUNDS = 9; const uint DWMWA_EXTENDED_FRAME_BOUNDS = 9;
return 0 == DwmGetWindowAttribute(handle, DWMWA_EXTENDED_FRAME_BOUNDS, return 0 == DwmGetWindowAttribute(handle, DWMWA_EXTENDED_FRAME_BOUNDS,
out rect, (uint)Marshal.SizeOf<Rect>()); out rect, (uint)Marshal.SizeOf<RECT>());
}
public static IntPtr GetWindowLong(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size == 8)
return GetWindowLongPtr(hWnd, nIndex);
else
return GetWindowLong32(hWnd, nIndex);
}
public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong)
{
if (IntPtr.Size == 8)
return SetWindowLongPtr(hWnd, nIndex, dwNewLong);
else
return SetWindowLong32(hWnd, nIndex, dwNewLong);
} }
public static string GetAppPathForExtension(params string[] extensions) public static string GetAppPathForExtension(params string[] extensions)

View File

@@ -21,7 +21,7 @@ public static class WinApi
public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags); public static extern uint ActivateKeyboardLayout(IntPtr hkl, uint flags);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, out Rect lpRect); public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("user32.dll", CharSet = CharSet.Unicode)] [DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindowEx( public static extern IntPtr FindWindowEx(
@@ -49,28 +49,19 @@ public static class WinApi
public static extern int GetDpiForWindow(IntPtr hwnd); public static extern int GetDpiForWindow(IntPtr hwnd);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool AdjustWindowRect(ref Rect lpRect, uint dwStyle, bool bMenu); public static extern bool AdjustWindowRect(ref RECT lpRect, uint dwStyle, bool bMenu);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool AdjustWindowRectExForDpi( public static extern bool AdjustWindowRectExForDpi(
ref Rect lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi); ref RECT lpRect, uint dwStyle, bool bMenu, uint dwExStyle, uint dpi);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern bool SetWindowPos( public static extern bool SetWindowPos(
IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
public static extern IntPtr GetWindowLong32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")] [DllImport("user32.dll")]
public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex); public static extern IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern IntPtr SetWindowLong32(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll")]
public static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("gdi32.dll")] [DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
@@ -80,17 +71,17 @@ public static class WinApi
[DllImport("dwmapi.dll")] [DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute( public static extern int DwmGetWindowAttribute(
IntPtr hwnd, uint dwAttribute, out Rect pvAttribute, uint cbAttribute); IntPtr hwnd, uint dwAttribute, out RECT pvAttribute, uint cbAttribute);
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Rect public struct RECT
{ {
public int Left; public int Left;
public int Top; public int Top;
public int Right; public int Right;
public int Bottom; public int Bottom;
public Rect(Rectangle r) public RECT(Rectangle r)
{ {
Left = r.Left; Left = r.Left;
Top = r.Top; Top = r.Top;
@@ -98,7 +89,7 @@ public static class WinApi
Bottom = r.Bottom; Bottom = r.Bottom;
} }
public Rect(int left, int top, int right, int bottom) public RECT(int left, int top, int right, int bottom)
{ {
Left = left; Left = left;
Top = top; Top = top;
@@ -111,9 +102,9 @@ public static class WinApi
public int Width => Right - Left; public int Width => Right - Left;
public int Height => Bottom - Top; public int Height => Bottom - Top;
public static Rect FromRectangle(Rectangle rect) public static RECT FromRectangle(Rectangle rect)
{ {
return new Rect(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height); return new RECT(rect.X, rect.Y, rect.X + rect.Width, rect.Y + rect.Height);
} }
public override string ToString() public override string ToString()
@@ -125,14 +116,14 @@ public static class WinApi
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct NCCALCSIZE_PARAMS public struct NCCALCSIZE_PARAMS
{ {
public NCCALCSIZE_PARAMS(Rect[] r, WINDOWPOS wp) public NCCALCSIZE_PARAMS(RECT[] r, WINDOWPOS wp)
{ {
rgrc = r; rgrc = r;
lppos = wp; lppos = wp;
} }
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public Rect[] rgrc; public RECT[] rgrc;
public WINDOWPOS lppos; public WINDOWPOS lppos;
} }

View File

@@ -1,8 +1,7 @@
{ {
"profiles": { "profiles": {
"MpvNet.Windows": { "MpvNet.Windows": {
"commandName": "Project", "commandName": "Project"
"commandLineArgs": "\"E:\\Video\\Samples\\LG New York HDR UHD 4K Demo.mkv\""
} }
} }
} }

View File

@@ -534,7 +534,7 @@ name = title-bar
file = mpv file = mpv
default = yes default = yes
directory = Window directory = Window
help = Shows the window title bar. help = Set this to no in order to hide the window title bar.
option = yes option = yes
option = no option = no

View File

@@ -21,8 +21,6 @@ using CommunityToolkit.Mvvm.Messaging;
using static MpvNet.Windows.Native.WinApi; using static MpvNet.Windows.Native.WinApi;
using static MpvNet.Windows.Help.WinApiHelp; using static MpvNet.Windows.Help.WinApiHelp;
using System.Numerics;
using System.Windows.Media.Media3D;
namespace MpvNet.Windows.WinForms; namespace MpvNet.Windows.WinForms;
@@ -43,10 +41,10 @@ public partial class MainForm : Form
int _lastCursorChanged; int _lastCursorChanged;
int _lastCycleFullscreen; int _lastCycleFullscreen;
int _taskbarButtonCreatedMessage; int _taskbarButtonCreatedMessage;
int _nactivateHeight;
bool _contextMenuIsReady; bool _contextMenuIsReady;
bool _wasMaximized; bool _wasMaximized;
bool _maxSizeSet;
public MainForm() public MainForm()
{ {
@@ -663,7 +661,7 @@ public partial class MainForm : Form
} }
Point middlePos = new Point(Left + Width / 2, Top + Height / 2); Point middlePos = new Point(Left + Width / 2, Top + Height / 2);
var rect = new Rect(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height)); var rect = new RECT(new Rectangle(screen.Bounds.X, screen.Bounds.Y, width, height));
AddWindowBorders(Handle, ref rect, GetDpi(Handle), !Player.TitleBar); AddWindowBorders(Handle, ref rect, GetDpi(Handle), !Player.TitleBar);
@@ -965,8 +963,6 @@ public partial class MainForm : Form
protected override void WndProc(ref Message m) protected override void WndProc(ref Message m)
{ {
//Debug.WriteLine(m);
switch (m.Msg) switch (m.Msg)
{ {
case 0x0007: // WM_SETFOCUS case 0x0007: // WM_SETFOCUS
@@ -1026,9 +1022,6 @@ public partial class MainForm : Form
case 0x51: // WM_INPUTLANGCHANGE case 0x51: // WM_INPUTLANGCHANGE
ActivateKeyboardLayout(m.LParam, 0x00000100u /*KLF_SETFORPROCESS*/); ActivateKeyboardLayout(m.LParam, 0x00000100u /*KLF_SETFORPROCESS*/);
break; break;
//case 0x0086: // WM_NCACTIVATE
// _nactivateHeight = Height;
// break;
case 0x319: // WM_APPCOMMAND case 0x319: // WM_APPCOMMAND
{ {
string? value = MpvHelp.WM_APPCOMMAND_to_mpv_key((int)(m.LParam.ToInt64() >> 16 & ~0xf000)); string? value = MpvHelp.WM_APPCOMMAND_to_mpv_key((int)(m.LParam.ToInt64() >> 16 & ~0xf000));
@@ -1065,50 +1058,44 @@ public partial class MainForm : Form
if (!WasShown) if (!WasShown)
break; break;
Rect rect = Marshal.PtrToStructure<Rect>(m.LParam); RECT rect = Marshal.PtrToStructure<RECT>(m.LParam);
SetWindowPos(Handle, IntPtr.Zero, rect.Left, rect.Top, rect.Width, rect.Height, 0); SetWindowPos(Handle, IntPtr.Zero, rect.Left, rect.Top, rect.Width, rect.Height, 0);
} }
break; break;
case 0x0112: // WM_SYSCOMMAND
{
// with title-bar=no when the window is restored from minimizing the height is too high
if (!Player.TitleBar)
{
int SC_MINIMIZE = 0xF020;
if (m.WParam == (nint)SC_MINIMIZE)
{
MaximumSize = Size;
_maxSizeSet = true;
}
}
}
break;
case 0x0083: // WM_NCCALCSIZE case 0x0083: // WM_NCCALCSIZE
if (m.WParam != IntPtr.Zero && m.LParam != IntPtr.Zero && Player.Border && if ((int)m.WParam == 1 && !Player.TitleBar && !IsFullscreen)
!Player.TitleBar && !IsFullscreen && WindowState != FormWindowState.Minimized)
{ {
var nccalcsize_params = Marshal.PtrToStructure<NCCALCSIZE_PARAMS>(m.LParam); var nccalcsize_params = Marshal.PtrToStructure<NCCALCSIZE_PARAMS>(m.LParam);
Rect[] rects = nccalcsize_params.rgrc; RECT[] rects = nccalcsize_params.rgrc;
rects[0].Top = rects[0].Top - GetTitleBarHeight(Handle, GetDpi(Handle)); rects[0].Top = rects[0].Top - GetTitleBarHeight(Handle, GetDpi(Handle));
Marshal.StructureToPtr(nccalcsize_params, m.LParam, false); Marshal.StructureToPtr(nccalcsize_params, m.LParam, false);
} }
_skipWM_NCCALCSIZE = false;
break; break;
case 0x231: // WM_ENTERSIZEMOVE
case 0x005: // WM_SIZE case 0x005: // WM_SIZE
{
int hiWord = (short)(m.LParam.ToInt32() >> 16); // HiWord
Debug.WriteLine(hiWord);
}
if (m.WParam == (nint)1) // SIZE_RESTORED=0, SIZE_MINIMIZED=1
{
_skipWM_NCCALCSIZE = true;
//if (Player.VideoSize != Size.Empty)
//{
// //int w = ClientSize.Width;
// //int h = (int)Math.Floor(w * Player.VideoSize.Height / (double)Player.VideoSize.Width);
// //var rect = new Rect(new Rectangle(0, 0, w, h));
// //AddWindowBorders(Handle, ref rect, GetDpi(Handle), !Player.TitleBar);
// //Height = rect.Height;
// ////ClientSize = new Size(w, h);
//}
}
if (Player.SnapWindow) if (Player.SnapWindow)
SnapManager.OnSizeAndEnterSizeMove(this); SnapManager.OnSizeAndEnterSizeMove(this);
break; break;
case 0x214: // WM_SIZING case 0x214: // WM_SIZING
Debug.WriteLine("WM_SIZING");
if (Player.KeepaspectWindow) if (Player.KeepaspectWindow)
{ {
Rect rc = Marshal.PtrToStructure<Rect>(m.LParam); RECT rc = Marshal.PtrToStructure<RECT>(m.LParam);
Rect r = rc; RECT r = rc;
SubtractWindowBorders(Handle, ref r, GetDpi(Handle), !Player.TitleBar); SubtractWindowBorders(Handle, ref r, GetDpi(Handle), !Player.TitleBar);
int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top; int c_w = r.Right - r.Left, c_h = r.Bottom - r.Top;
@@ -1128,7 +1115,7 @@ public partial class MainForm : Form
if (corner >= 0) if (corner >= 0)
corners[corner] -= d_corners[corner]; corners[corner] -= d_corners[corner];
Marshal.StructureToPtr(new Rect(corners[0], corners[1], corners[2], corners[3]), m.LParam, false); Marshal.StructureToPtr(new RECT(corners[0], corners[1], corners[2], corners[3]), m.LParam, false);
m.Result = new IntPtr(1); m.Result = new IntPtr(1);
} }
return; return;
@@ -1198,38 +1185,10 @@ public partial class MainForm : Form
Activate(); Activate();
} }
return; return;
case 0x231: // WM_ENTERSIZEMOVE
if (Player.SnapWindow)
SnapManager.OnSizeAndEnterSizeMove(this);
break;
case 0x216: // WM_MOVING case 0x216: // WM_MOVING
if (Player.SnapWindow) if (Player.SnapWindow)
SnapManager.OnMoving(ref m); SnapManager.OnMoving(ref m);
break; break;
case 0x0006: // WM_ACTIVATE
{
int loWord = (short)(m.WParam.ToInt32() & 0xFFFF);
bool deactivate = loWord == 0;
if (deactivate)
{
//Debug.WriteLine("deactivate: " + Height);
_nactivateHeight = Height;
}
else
{
//Debug.WriteLine("activate: " + Height);
if (_nactivateHeight != 0)
{
Height = _nactivateHeight;
_nactivateHeight = 0;
}
}
}
break;
} }
if (m.Msg == _taskbarButtonCreatedMessage && Player.TaskbarProgress) if (m.Msg == _taskbarButtonCreatedMessage && Player.TaskbarProgress)
@@ -1243,7 +1202,24 @@ public partial class MainForm : Form
base.WndProc(ref m); base.WndProc(ref m);
} }
bool _skipWM_NCCALCSIZE; protected override void OnActivated(EventArgs e)
{
base.OnActivated(e);
if (_maxSizeSet)
{
TaskHelp.Run(() => {
Thread.Sleep(200);
BeginInvoke(() => {
if (!IsDisposed && !Disposing)
{
MaximumSize = new Size(int.MaxValue, int.MaxValue);
_maxSizeSet = false;
}
});
});
}
}
void CursorTimer_Tick(object sender, EventArgs e) void CursorTimer_Tick(object sender, EventArgs e)
{ {
@@ -1337,6 +1313,8 @@ public partial class MainForm : Form
BeginInvoke(() => { BeginInvoke(() => {
SetSize(ClientSize.Width, ClientSize.Height, Screen.FromControl(this), false); SetSize(ClientSize.Width, ClientSize.Height, Screen.FromControl(this), false);
Height += 1;
Height -= 1;
}); });
} }

View File

@@ -51,7 +51,7 @@ public class SnapManager
if (Handle == IntPtr.Zero) if (Handle == IntPtr.Zero)
return; return;
WinApi.Rect boundsLtrb = Marshal.PtrToStructure<WinApi.Rect>(m.LParam); WinApi.RECT boundsLtrb = Marshal.PtrToStructure<WinApi.RECT>(m.LParam);
Rectangle bounds = boundsLtrb.ToRectangle(); Rectangle bounds = boundsLtrb.ToRectangle();
// This is where the window _would_ be located if snapping // This is where the window _would_ be located if snapping
// had not occurred. This prevents the cursor from sliding // had not occurred. This prevents the cursor from sliding
@@ -62,7 +62,7 @@ public class SnapManager
bounds.Width, bounds.Width,
bounds.Height); bounds.Height);
FindSnap(ref effectiveBounds); FindSnap(ref effectiveBounds);
WinApi.Rect newLtrb = WinApi.Rect.FromRectangle(effectiveBounds); WinApi.RECT newLtrb = WinApi.RECT.FromRectangle(effectiveBounds);
Marshal.StructureToPtr(newLtrb, m.LParam, false); Marshal.StructureToPtr(newLtrb, m.LParam, false);
m.Result = new IntPtr(1); m.Result = new IntPtr(1);
} }