Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When the titlebar is clicked, dismiss the new tab flyout #2438

Merged
2 commits merged into from
Aug 16, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/cascadia/TerminalApp/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1462,6 +1462,23 @@ namespace winrt::TerminalApp::implementation
return connection;
}

// Method Description:
// - Used to tell the app that the titlebar has been clicked. The App won't
// actually recieve any clicks in the titlebar area, so this is a helper
// to clue the app in that a click has happened. The App will use this as
// a indicator that it needs to dismiss any open flyouts.
// Arguments:
// - <none>
// Return Value:
// - <none>
void App::TitlebarClicked()
{
if (_newTabButton && _newTabButton.Flyout())
{
_newTabButton.Flyout().Hide();
}
}

// -------------------------------- WinRT Events ---------------------------------
// Winrt events need a method for adding a callback to the event and removing the callback.
// These macros will define them both for you.
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace winrt::TerminalApp::implementation
~App() = default;

hstring GetTitle();
void TitlebarClicked();

// -------------------------------- WinRT Events ---------------------------------
DECLARE_EVENT(TitleChanged, _titleChangeHandlers, winrt::Microsoft::Terminal::TerminalControl::TitleChangedEventArgs);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/App.idl
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<App, Windows.UI.Xaml.ElementTheme> RequestedThemeChanged;

String GetTitle();

void TitlebarClicked();
}
}
5 changes: 5 additions & 0 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ void AppHost::Initialize()
// This has to be done _before_ App::Create, as the app might set the
// content in Create.
_app.SetTitleBarContent({ this, &AppHost::_UpdateTitleBarContent });

// Add an event handler to plumb clicks in the titlebar area down to the
// application layer.
auto pNcWindow = static_cast<NonClientIslandWindow*>(_window.get());
pNcWindow->DragRegionClicked([this]() { _app.TitlebarClicked(); });
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
}
_app.RequestedThemeChanged({ this, &AppHost::_UpdateTheme });

Expand Down
31 changes: 23 additions & 8 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,22 @@ void NonClientIslandWindow::_UpdateDragRegion()
// - Hit test the frame for resizing and moving.
// Arguments:
// - ptMouse: the mouse point being tested, in absolute (NOT WINDOW) coordinates.
// - titlebarIsCaption: If true, we want to treat the titlebar area as
// HTCAPTION, otherwise we'll return HTNOWHERE for the titlebar.
// Return Value:
// - one of the values from
// https://docs.microsoft.com/en-us/windows/desktop/inputdev/wm-nchittest#return-value
// corresponding to the area of the window that was hit
// NOTE:
// Largely taken from code on:
// - Largely taken from code on:
// https://docs.microsoft.com/en-us/windows/desktop/dwm/customframe
[[nodiscard]] LRESULT NonClientIslandWindow::HitTestNCA(POINT ptMouse) const noexcept
// NOTE[2]: Concerning `titlebarIsCaption`
// - We want HTNOWHERE as the return value for WM_NCHITTEST, so that we can get
// mouse presses in the titlebar area. If we return HTCAPTION there, we won't
// get any mouse WMs. However, when we're handling the mouse events, we need
// to know if the mouse was in that are or not, so we'll return HTCAPTION in
// that handler, to differentiate from the rest of the window.
[[nodiscard]] LRESULT NonClientIslandWindow::HitTestNCA(POINT ptMouse, const bool titlebarIsCaption) const noexcept
{
// Get the window rectangle.
RECT rcWindow = BaseWindow::GetWindowRect();
Expand Down Expand Up @@ -311,10 +319,11 @@ void NonClientIslandWindow::_UpdateDragRegion()

// clang-format off
// Hit test (HTTOPLEFT, ... HTBOTTOMRIGHT)
const auto topHt = fOnResizeBorder ? HTTOP : (titlebarIsCaption ? HTCAPTION : HTNOWHERE);
LRESULT hitTests[3][3] = {
{ HTTOPLEFT, fOnResizeBorder ? HTTOP : HTCAPTION, HTTOPRIGHT },
{ HTLEFT, HTNOWHERE, HTRIGHT },
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
{ HTTOPLEFT, topHt, HTTOPRIGHT },
{ HTLEFT, HTNOWHERE, HTRIGHT },
{ HTBOTTOMLEFT, HTBOTTOM, HTBOTTOMRIGHT },
};
// clang-format on

Expand Down Expand Up @@ -511,8 +520,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
// Handle hit testing in the NCA if not handled by DwmDefWindowProc.
if (lRet == 0)
{
lRet = HitTestNCA({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) });

lRet = HitTestNCA({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }, false);
if (lRet != HTNOWHERE)
{
return lRet;
Expand Down Expand Up @@ -594,9 +602,14 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
{
POINT point1 = {};
::GetCursorPos(&point1);
const auto region = HitTestNCA(point1);

const auto region = HitTestNCA(point1, true);
if (region == HTCAPTION)
{
// If we clicked in the titlebar, raise an event so the app host can
// dispatch an appropriate event.
_DragRegionClickedHandlers();

const auto longParam = MAKELPARAM(point1.x, point1.y);
::SetActiveWindow(_window.get());
::PostMessage(_window.get(), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, longParam);
Expand Down Expand Up @@ -798,3 +811,5 @@ bool NonClientIslandWindow::_HandleWindowPosChanging(WINDOWPOS* const windowPos)
}
return true;
}

DEFINE_EVENT(NonClientIslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);
5 changes: 4 additions & 1 deletion src/cascadia/WindowsTerminal/NonClientIslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Author(s):
#include <dwmapi.h>
#include <windowsx.h>
#include <wil\resource.h>
#include "../../cascadia/inc/cppwinrt_utils.h"

class NonClientIslandWindow : public IslandWindow
{
Expand All @@ -42,6 +43,8 @@ class NonClientIslandWindow : public IslandWindow
void SetContent(winrt::Windows::UI::Xaml::UIElement content) override;
void SetTitlebarContent(winrt::Windows::UI::Xaml::UIElement content);

DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>);

private:
winrt::TerminalApp::TitlebarControl _titlebar{ nullptr };
winrt::Windows::UI::Xaml::UIElement _clientContent{ nullptr };
Expand All @@ -55,7 +58,7 @@ class NonClientIslandWindow : public IslandWindow

RECT GetDragAreaRect() const noexcept;

[[nodiscard]] LRESULT HitTestNCA(POINT ptMouse) const noexcept;
[[nodiscard]] LRESULT HitTestNCA(POINT ptMouse, const bool titlebarIsCaption) const noexcept;

[[nodiscard]] HRESULT _UpdateFrameMargins() const noexcept;

Expand Down