#include "mpv_container.h" #include namespace mpv { MpvContainer* MpvContainer::GetInstance() { return instance_.get(); } HWND MpvContainer::Create() { auto window_class = WNDCLASSEX{}; ::SecureZeroMemory(&window_class, sizeof(window_class)); window_class.cbSize = sizeof(window_class); window_class.style = 0; window_class.lpfnWndProc = WindowProc; window_class.hInstance = GetModuleHandle(nullptr); window_class.lpszClassName = kClassName; window_class.hCursor = ::LoadCursorW(nullptr, IDC_ARROW); window_class.hbrBackground = ::CreateSolidBrush(RGB(0, 0, 0)); ::RegisterClassExW(&window_class); // Use WS_POPUP for a borderless window without title bar. // Use WS_EX_TOOLWINDOW | WS_EX_NOREDIRECTIONBITMAP to prevent shadow and DWM effects. handle_ = ::CreateWindowExW( WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_NOREDIRECTIONBITMAP, kClassName, kWindowName, WS_POPUP, 0, 0, 100, 100, nullptr, nullptr, GetModuleHandle(nullptr), nullptr); // Disable DWM animations on the container. auto disable_window_transitions = TRUE; DwmSetWindowAttribute( handle_, DWMWA_TRANSITIONS_FORCEDISABLED, &disable_window_transitions, sizeof(disable_window_transitions)); return handle_; } HWND MpvContainer::Get(HWND flutter_window) { if (!handle_) { Create(); } RECT window_rect; ::GetWindowRect(flutter_window, &window_rect); ::SetWindowPos( handle_, flutter_window, window_rect.left, window_rect.top, window_rect.right - window_rect.left, window_rect.bottom - window_rect.top, SWP_NOACTIVATE); ::SetWindowLongPtr(handle_, GWLP_USERDATA, reinterpret_cast(flutter_window)); ::ShowWindow(handle_, SW_SHOWNOACTIVATE); ::SetFocus(flutter_window); return handle_; } LRESULT CALLBACK MpvContainer::WindowProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept { switch (message) { case WM_DESTROY: { ::PostQuitMessage(0); return 0; } case WM_MOUSEMOVE: case WM_SIZE: case WM_MOVE: case WM_MOVING: case WM_ACTIVATE: case WM_WINDOWPOSCHANGED: { // Redirect focus to Flutter window. auto user_data = ::GetWindowLongPtr(window, GWLP_USERDATA); if (user_data) { ::SetForegroundWindow(reinterpret_cast(user_data)); } break; } case WM_ERASEBKGND: { // Prevent erasing to avoid flicker. return 1; } default: break; } return ::DefWindowProc(window, message, wparam, lparam); } std::unique_ptr MpvContainer::instance_ = std::make_unique(); } // namespace mpv