Ayman Bagabas 814f78ed2c
Add support for VT horizontal mouse wheel events (#19248)
This adds support for horizontal mouse wheel events (`WM_MOUSEHWHEEL`).
With this change, applications running in the terminal can now receive
and respond to horizontal scroll inputs from the mouse/trackpad.

Closes #19245
Closes #10329
2025-09-11 18:48:49 -05:00

167 lines
6.4 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "BaseWindow.h"
struct SystemMenuItemInfo
{
winrt::hstring label;
winrt::delegate<void()> callback;
};
class IslandWindow :
public BaseWindow<IslandWindow>
{
public:
static bool IsCursorHidden() noexcept;
static void HideCursor() noexcept;
static void ShowCursorMaybe(const UINT message) noexcept;
IslandWindow() noexcept;
~IslandWindow();
virtual void MakeWindow() noexcept;
virtual void Close();
virtual void OnSize(const UINT width, const UINT height);
HWND GetInteropHandle() const;
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
[[nodiscard]] LRESULT OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept;
void OnResize(const UINT width, const UINT height);
void OnMinimize();
void OnRestore();
virtual void OnAppInitialized();
virtual void SetContent(winrt::Windows::UI::Xaml::UIElement content);
virtual void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme);
virtual til::rect GetNonClientFrame(const UINT dpi) const noexcept;
virtual til::size GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept;
virtual void Initialize();
void SetCreateCallback(std::function<void(const HWND, const til::rect&)> pfn) noexcept;
void SetSnapDimensionCallback(std::function<float(bool widthOrHeight, float dimension)> pfn) noexcept;
void FocusModeChanged(const bool focusMode);
void FullscreenChanged(const bool fullscreen);
void SetAlwaysOnTop(const bool alwaysOnTop);
void ShowWindowChanged(const bool showOrHide);
virtual void SetShowTabsFullscreen(const bool newShowTabsFullscreen);
void FlashTaskbar();
void SetTaskbarProgress(const size_t state, const size_t progress);
void SummonWindow(winrt::TerminalApp::SummonWindowBehavior args);
bool IsQuakeWindow() const noexcept;
void IsQuakeWindow(bool isQuakeWindow) noexcept;
void SetAutoHideWindow(bool autoHideWindow) noexcept;
void HideWindow();
void SetMinimizeToNotificationAreaBehavior(bool MinimizeToNotificationArea) noexcept;
void OpenSystemMenu(const std::optional<int> mouseX, const std::optional<int> mouseY) const noexcept;
void AddToSystemMenu(const winrt::hstring& itemLabel, winrt::delegate<void()> callback);
void RemoveFromSystemMenu(const winrt::hstring& itemLabel);
void UseDarkTheme(const bool v);
virtual void UseMica(const bool newValue, const double titlebarOpacity);
til::event<winrt::delegate<>> DragRegionClicked;
til::event<winrt::delegate<>> WindowCloseButtonClicked;
til::event<winrt::delegate<void(winrt::Windows::Foundation::Point, winrt::Microsoft::Terminal::Core::Point)>> MouseScrolled;
til::event<winrt::delegate<void(bool)>> WindowActivated;
til::event<winrt::delegate<void()>> NotifyNotificationIconPressed;
til::event<winrt::delegate<void()>> NotifyWindowHidden;
til::event<winrt::delegate<void(HMENU, UINT)>> NotifyNotificationIconMenuItemSelected;
til::event<winrt::delegate<void()>> NotifyReAddNotificationIcon;
til::event<winrt::delegate<void()>> ShouldExitFullscreen;
til::event<winrt::delegate<void(bool)>> MaximizeChanged;
til::event<winrt::delegate<void()>> WindowMoved;
til::event<winrt::delegate<void(bool)>> WindowVisibilityChanged;
protected:
void ForceResize()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.width, size.height);
}
HWND _interopWindowHandle;
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source; // nulled in ctor
winrt::Windows::UI::Xaml::Controls::Grid _rootGrid; // nulled in ctor
wil::com_ptr<ITaskbarList3> _taskbar;
std::function<void(const HWND, const til::rect&)> _pfnCreateCallback;
std::function<float(bool, float)> _pfnSnapDimensionCallback;
void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept;
[[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam);
[[nodiscard]] LRESULT _OnMoving(const WPARAM wParam, const LPARAM lParam);
bool _borderless{ false };
bool _alwaysOnTop{ false };
bool _fullscreen{ false };
bool _showTabsFullscreen{ false };
bool _fWasMaximizedBeforeFullscreen{ false };
RECT _rcWindowBeforeFullscreen{};
RECT _rcWorkBeforeFullscreen{};
UINT _dpiBeforeFullscreen{ 96 };
virtual void _SetIsBorderless(const bool borderlessEnabled);
virtual void _SetIsFullscreen(const bool fullscreenEnabled);
void _RestoreFullscreenPosition(const RECT& rcWork);
void _SetFullscreenPosition(const RECT& rcMonitor, const RECT& rcWork);
LONG _getDesiredWindowStyle() const;
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
void _globalActivateWindow(const uint32_t dropdownDuration,
const winrt::TerminalApp::MonitorBehavior toMonitor);
void _dropdownWindow(const uint32_t dropdownDuration,
const winrt::TerminalApp::MonitorBehavior toMonitor);
void _slideUpWindow(const uint32_t dropdownDuration);
void _doSlideAnimation(const uint32_t dropdownDuration, const bool down);
void _globalDismissWindow(const uint32_t dropdownDuration);
static MONITORINFO _getMonitorForCursor();
static MONITORINFO _getMonitorForWindow(HWND foregroundWindow);
void _moveToMonitor(HWND foregroundWindow, const winrt::TerminalApp::MonitorBehavior toMonitor);
void _moveToMonitorOfMouse();
void _moveToMonitorOf(HWND foregroundWindow);
void _moveToMonitor(const MONITORINFO activeMonitor);
bool _isQuakeWindow{ false };
bool _autoHideWindow{ false };
void _enterQuakeMode();
til::rect _getQuakeModeSize(HMONITOR hmon);
bool _minimizeToNotificationArea{ false };
std::unordered_map<UINT, SystemMenuItemInfo> _systemMenuItems;
UINT _systemMenuNextItemId = 0;
void _resetSystemMenu();
private:
// This minimum width allows for width the tabs fit
static constexpr float minimumWidth = 460;
// We run with no height requirement for client area,
// though the total height will take into account the non-client area
// and the requirements of components hosted in the client area
static constexpr float minimumHeight = 0;
inline static bool _cursorHidden;
};