Fix media viewer with MacBook top notch.

This commit is contained in:
John Preston 2023-07-25 12:30:52 +04:00
parent b7ea9a2837
commit 8cc90c3373
9 changed files with 135 additions and 26 deletions

View file

@ -388,6 +388,8 @@ void Controller::initLayout() {
_layout = _wrap->sizeValue( _layout = _wrap->sizeValue(
) | rpl::map([=](QSize size) { ) | rpl::map([=](QSize size) {
const auto topNotchSkip = _delegate->storiesTopNotchSkip();
size = QSize( size = QSize(
std::max(size.width(), st::mediaviewMinWidth), std::max(size.width(), st::mediaviewMinWidth),
std::max(size.height(), st::mediaviewMinHeight)); std::max(size.height(), st::mediaviewMinHeight));
@ -397,7 +399,8 @@ void Controller::initLayout() {
? HeaderLayout::Outside ? HeaderLayout::Outside
: HeaderLayout::Normal; : HeaderLayout::Normal;
const auto topSkip = st::storiesFieldMargin.bottom() const auto topSkip = topNotchSkip
+ st::storiesFieldMargin.bottom()
+ (layout.headerLayout == HeaderLayout::Outside + (layout.headerLayout == HeaderLayout::Outside
? outsideHeaderHeight ? outsideHeaderHeight
: 0); : 0);

View file

@ -64,6 +64,7 @@ public:
virtual void storiesVolumeToggle() = 0; virtual void storiesVolumeToggle() = 0;
virtual void storiesVolumeChanged(float64 volume) = 0; virtual void storiesVolumeChanged(float64 volume) = 0;
virtual void storiesVolumeChangeFinished() = 0; virtual void storiesVolumeChangeFinished() = 0;
[[nodiscard]] virtual int storiesTopNotchSkip() = 0;
}; };
} // namespace Media::Stories } // namespace Media::Stories

View file

@ -21,7 +21,8 @@ namespace {
using namespace Ui::GL; using namespace Ui::GL;
constexpr auto kRadialLoadingOffset = 4; constexpr auto kNotchOffset = 4;
constexpr auto kRadialLoadingOffset = kNotchOffset + 4;
constexpr auto kThemePreviewOffset = kRadialLoadingOffset + 4; constexpr auto kThemePreviewOffset = kRadialLoadingOffset + 4;
constexpr auto kDocumentBubbleOffset = kThemePreviewOffset + 4; constexpr auto kDocumentBubbleOffset = kThemePreviewOffset + 4;
constexpr auto kSaveMsgOffset = kDocumentBubbleOffset + 4; constexpr auto kSaveMsgOffset = kDocumentBubbleOffset + 4;
@ -129,7 +130,7 @@ OverlayWidget::RendererGL::RendererGL(not_null<OverlayWidget*> owner)
void OverlayWidget::RendererGL::init( void OverlayWidget::RendererGL::init(
not_null<QOpenGLWidget*> widget, not_null<QOpenGLWidget*> widget,
QOpenGLFunctions &f) { QOpenGLFunctions &f) {
constexpr auto kQuads = 8; constexpr auto kQuads = 9;
constexpr auto kQuadVertices = kQuads * 4; constexpr auto kQuadVertices = kQuads * 4;
constexpr auto kQuadValues = kQuadVertices * 4; constexpr auto kQuadValues = kQuadVertices * 4;
constexpr auto kControlsValues = kControlsCount * kControlValues; constexpr auto kControlsValues = kControlsCount * kControlValues;
@ -291,6 +292,28 @@ bool OverlayWidget::RendererGL::handleHideWorkaround(QOpenGLFunctions &f) {
void OverlayWidget::RendererGL::paintBackground() { void OverlayWidget::RendererGL::paintBackground() {
_contentBuffer->bind(); _contentBuffer->bind();
if (const auto notch = _owner->topNotchSkip()) {
const auto top = transformRect(QRect(0, 0, _owner->width(), notch));
const GLfloat coords[] = {
top.left(), top.top(),
top.right(), top.top(),
top.right(), top.bottom(),
top.left(), top.bottom(),
};
const auto offset = kNotchOffset;
_contentBuffer->write(
offset * 4 * sizeof(GLfloat),
coords,
sizeof(coords));
_fillProgram->bind();
_fillProgram->setUniformValue("viewport", _uniformViewport);
FillRectangle(
*_f,
&*_fillProgram,
offset,
QColor(0, 0, 0));
}
} }
void OverlayWidget::RendererGL::paintTransformedVideoFrame( void OverlayWidget::RendererGL::paintTransformedVideoFrame(

View file

@ -45,6 +45,12 @@ void OverlayWidget::RendererSW::paintBackground() {
for (const auto &rect : region) { for (const auto &rect : region) {
_p->fillRect(rect, bg); _p->fillRect(rect, bg);
} }
if (const auto notch = _owner->topNotchSkip()) {
const auto top = QRect(0, 0, _owner->width(), notch);
if (const auto black = top.intersected(_clipOuter); !black.isEmpty()) {
_p->fillRect(black, Qt::black);
}
}
_p->setCompositionMode(m); _p->setCompositionMode(m);
} }
@ -101,8 +107,8 @@ void OverlayWidget::RendererSW::paintTransformedStaticContent(
} }
void OverlayWidget::RendererSW::paintControlsFade( void OverlayWidget::RendererSW::paintControlsFade(
QRect content, QRect content,
const ContentGeometry &geometry) { const ContentGeometry &geometry) {
auto opacity = geometry.controlsOpacity; auto opacity = geometry.controlsOpacity;
if (geometry.fade > 0.) { if (geometry.fade > 0.) {
_p->setOpacity(geometry.fade); _p->setOpacity(geometry.fade);

View file

@ -587,6 +587,16 @@ OverlayWidget::OverlayWidget()
update(); update();
}, lifetime()); }, lifetime());
_helper->topNotchSkipValue(
) | rpl::start_with_next([=](int notch) {
if (_topNotchSize != notch) {
_topNotchSize = notch;
if (_fullscreen) {
updateControlsGeometry();
}
}
}, lifetime());
_window->setTitle(tr::lng_mediaview_title(tr::now)); _window->setTitle(tr::lng_mediaview_title(tr::now));
_window->setTitleStyle(st::mediaviewTitle); _window->setTitleStyle(st::mediaviewTitle);
@ -673,7 +683,11 @@ void OverlayWidget::showSaveMsgToastWith(
const auto h = st::mediaviewSaveMsgStyle.font->height const auto h = st::mediaviewSaveMsgStyle.font->height
+ st::mediaviewSaveMsgPadding.top() + st::mediaviewSaveMsgPadding.top()
+ st::mediaviewSaveMsgPadding.bottom(); + st::mediaviewSaveMsgPadding.bottom();
_saveMsg = QRect((width() - w) / 2, (height() - h) / 2, w, h); _saveMsg = QRect(
(width() - w) / 2,
_minUsedTop + (_maxUsedHeight - h) / 2,
w,
h);
const auto callback = [=](float64 value) { const auto callback = [=](float64 value) {
updateSaveMsg(); updateSaveMsg();
if (!_saveMsgAnimation.animating()) { if (!_saveMsgAnimation.animating()) {
@ -703,7 +717,7 @@ void OverlayWidget::setupWindow() {
&& _streamed->controls && _streamed->controls
&& _streamed->controls->dragging())) { && _streamed->controls->dragging())) {
return Flag::None | Flag(0); return Flag::None | Flag(0);
} else if ((_w > _widget->width() || _h > _widget->height()) } else if ((_w > _widget->width() || _h > _maxUsedHeight)
&& (widgetPoint.y() > st::mediaviewHeaderTop) && (widgetPoint.y() > st::mediaviewHeaderTop)
&& QRect(_x, _y, _w, _h).contains(widgetPoint)) { && QRect(_x, _y, _w, _h).contains(widgetPoint)) {
return Flag::None | Flag(0); return Flag::None | Flag(0);
@ -940,8 +954,14 @@ void OverlayWidget::updateGeometryToScreen(bool inMove) {
void OverlayWidget::updateControlsGeometry() { void OverlayWidget::updateControlsGeometry() {
updateNavigationControlsGeometry(); updateNavigationControlsGeometry();
_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2); _saveMsg.moveTo(
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize); (width() - _saveMsg.width()) / 2,
_minUsedTop + (_maxUsedHeight - _saveMsg.height()) / 2);
_photoRadialRect = QRect(
QPoint(
(width() - st::radialSize.width()) / 2,
_minUsedTop + (_maxUsedHeight - st::radialSize.height()) / 2),
st::radialSize);
const auto bottom = st::mediaviewShadowBottom.height(); const auto bottom = st::mediaviewShadowBottom.height();
const auto top = st::mediaviewShadowTop.size(); const auto top = st::mediaviewShadowTop.size();
@ -960,6 +980,9 @@ void OverlayWidget::updateControlsGeometry() {
} }
void OverlayWidget::updateNavigationControlsGeometry() { void OverlayWidget::updateNavigationControlsGeometry() {
_minUsedTop = topNotchSkip();
_maxUsedHeight = height() - _minUsedTop;
const auto overRect = QRect( const auto overRect = QRect(
QPoint(), QPoint(),
QSize(st::mediaviewIconOver, st::mediaviewIconOver)); QSize(st::mediaviewIconOver, st::mediaviewIconOver));
@ -969,14 +992,22 @@ void OverlayWidget::updateNavigationControlsGeometry() {
const auto navSkip = st::mediaviewHeaderTop; const auto navSkip = st::mediaviewHeaderTop;
const auto xLeft = _stories ? (_x - navSize) : 0; const auto xLeft = _stories ? (_x - navSize) : 0;
const auto xRight = _stories ? (_x + _w) : (width() - navSize); const auto xRight = _stories ? (_x + _w) : (width() - navSize);
_leftNav = QRect(xLeft, navSkip, navSize, height() - 2 * navSkip); _leftNav = QRect(
xLeft,
_minUsedTop + navSkip,
navSize,
_maxUsedHeight - 2 * navSkip);
_leftNavOver = _stories _leftNavOver = _stories
? QRect() ? QRect()
: style::centerrect(_leftNav, overRect); : style::centerrect(_leftNav, overRect);
_leftNavIcon = style::centerrect( _leftNavIcon = style::centerrect(
_leftNav, _leftNav,
_stories ? st::storiesLeft : st::mediaviewLeft); _stories ? st::storiesLeft : st::mediaviewLeft);
_rightNav = QRect(xRight, navSkip, navSize, height() - 2 * navSkip); _rightNav = QRect(
xRight,
_minUsedTop + navSkip,
navSize,
_maxUsedHeight - 2 * navSkip);
_rightNavOver = _stories _rightNavOver = _stories
? QRect() ? QRect()
: style::centerrect(_rightNav, overRect); : style::centerrect(_rightNav, overRect);
@ -1213,7 +1244,7 @@ void OverlayWidget::updateControls() {
if (_document && documentBubbleShown()) { if (_document && documentBubbleShown()) {
_docRect = QRect( _docRect = QRect(
(width() - st::mediaviewFileSize.width()) / 2, (width() - st::mediaviewFileSize.width()) / 2,
(height() - st::mediaviewFileSize.height()) / 2, _minUsedTop + (_maxUsedHeight - st::mediaviewFileSize.height()) / 2,
st::mediaviewFileSize.width(), st::mediaviewFileSize.width(),
st::mediaviewFileSize.height()); st::mediaviewFileSize.height());
_docIconRect = QRect( _docIconRect = QRect(
@ -1244,7 +1275,7 @@ void OverlayWidget::updateControls() {
} else { } else {
_docIconRect = QRect( _docIconRect = QRect(
(width() - st::mediaviewFileIconSize) / 2, (width() - st::mediaviewFileIconSize) / 2,
(height() - st::mediaviewFileIconSize) / 2, _minUsedTop + (_maxUsedHeight - st::mediaviewFileIconSize) / 2,
st::mediaviewFileIconSize, st::mediaviewFileIconSize,
st::mediaviewFileIconSize); st::mediaviewFileIconSize);
_docDownload->hide(); _docDownload->hide();
@ -1263,7 +1294,8 @@ void OverlayWidget::updateControls() {
_shareVisible = story && story->canShare(); _shareVisible = story && story->canShare();
_rotateVisible = !_themePreviewShown && !story; _rotateVisible = !_themePreviewShown && !story;
const auto navRect = [&](int i) { const auto navRect = [&](int i) {
return QRect(width() - st::mediaviewIconSize.width() * i, return QRect(
width() - st::mediaviewIconSize.width() * i,
height() - st::mediaviewIconSize.height(), height() - st::mediaviewIconSize.height(),
st::mediaviewIconSize.width(), st::mediaviewIconSize.width(),
st::mediaviewIconSize.height()); st::mediaviewIconSize.height());
@ -1302,12 +1334,27 @@ void OverlayWidget::updateControls() {
}(); }();
_dateText = d.isValid() ? Ui::FormatDateTime(d) : QString(); _dateText = d.isValid() ? Ui::FormatDateTime(d) : QString();
if (!_fromName.isEmpty()) { if (!_fromName.isEmpty()) {
_fromNameLabel.setText(st::mediaviewTextStyle, _fromName, Ui::NameTextOptions()); _fromNameLabel.setText(
_nameNav = QRect(st::mediaviewTextLeft, height() - st::mediaviewTextTop, qMin(_fromNameLabel.maxWidth(), width() / 3), st::mediaviewFont->height); st::mediaviewTextStyle,
_dateNav = QRect(st::mediaviewTextLeft + _nameNav.width() + st::mediaviewTextSkip, height() - st::mediaviewTextTop, st::mediaviewFont->width(_dateText), st::mediaviewFont->height); _fromName,
Ui::NameTextOptions());
_nameNav = QRect(
st::mediaviewTextLeft,
height() - st::mediaviewTextTop,
qMin(_fromNameLabel.maxWidth(), width() / 3),
st::mediaviewFont->height);
_dateNav = QRect(
st::mediaviewTextLeft + _nameNav.width() + st::mediaviewTextSkip,
height() - st::mediaviewTextTop,
st::mediaviewFont->width(_dateText),
st::mediaviewFont->height);
} else { } else {
_nameNav = QRect(); _nameNav = QRect();
_dateNav = QRect(st::mediaviewTextLeft, height() - st::mediaviewTextTop, st::mediaviewFont->width(_dateText), st::mediaviewFont->height); _dateNav = QRect(
st::mediaviewTextLeft,
height() - st::mediaviewTextTop,
st::mediaviewFont->width(_dateText),
st::mediaviewFont->height);
} }
updateHeader(); updateHeader();
refreshNavVisibility(); refreshNavVisibility();
@ -1363,9 +1410,9 @@ void OverlayWidget::refreshCaptionGeometry() {
_caption.maxWidth()); _caption.maxWidth());
const auto maxExpandedOuterHeight = (_stories const auto maxExpandedOuterHeight = (_stories
? (_h - st::storiesShadowTop.height()) ? (_h - st::storiesShadowTop.height())
: height()); : _maxUsedHeight);
const auto maxCollapsedOuterHeight = !_stories const auto maxCollapsedOuterHeight = !_stories
? (height() / 4) ? (_maxUsedHeight / 4)
: (_h / 3); : (_h / 3);
const auto maxExpandedHeight = maxExpandedOuterHeight const auto maxExpandedHeight = maxExpandedOuterHeight
- st::mediaviewCaptionPadding.top() - st::mediaviewCaptionPadding.top()
@ -1777,7 +1824,7 @@ void OverlayWidget::recountSkipTop() {
? height() ? height()
: (_streamed->controls->y() - st::mediaviewCaptionPadding.bottom()); : (_streamed->controls->y() - st::mediaviewCaptionPadding.bottom());
const auto skipHeightBottom = (height() - bottom); const auto skipHeightBottom = (height() - bottom);
_skipTop = std::min( _skipTop = _minUsedTop + std::min(
std::max( std::max(
st::mediaviewCaptionMargin.height(), st::mediaviewCaptionMargin.height(),
height() - _height - skipHeightBottom), height() - _height - skipHeightBottom),
@ -1785,7 +1832,7 @@ void OverlayWidget::recountSkipTop() {
_availableHeight = height() - skipHeightBottom - _skipTop; _availableHeight = height() - skipHeightBottom - _skipTop;
if (_fullScreenVideo && skipHeightBottom > 0 && _width > 0) { if (_fullScreenVideo && skipHeightBottom > 0 && _width > 0) {
const auto h = width() * _height / _width; const auto h = width() * _height / _width;
const auto topAllFit = height() - skipHeightBottom - h; const auto topAllFit = _maxUsedHeight - skipHeightBottom - h;
if (_skipTop > topAllFit) { if (_skipTop > topAllFit) {
_skipTop = std::max(topAllFit, 0); _skipTop = std::max(topAllFit, 0);
} }
@ -1818,12 +1865,12 @@ void OverlayWidget::resizeContentByScreenSize() {
}; };
if (_width > 0 && _height > 0) { if (_width > 0 && _height > 0) {
_zoomToDefault = countZoomFor(availableWidth, _availableHeight); _zoomToDefault = countZoomFor(availableWidth, _availableHeight);
_zoomToScreen = countZoomFor(width(), height()); _zoomToScreen = countZoomFor(width(), _maxUsedHeight);
} else { } else {
_zoomToDefault = _zoomToScreen = 0; _zoomToDefault = _zoomToScreen = 0;
} }
const auto usew = _fullScreenVideo ? width() : availableWidth; const auto usew = _fullScreenVideo ? width() : availableWidth;
const auto useh = _fullScreenVideo ? height() : _availableHeight; const auto useh = _fullScreenVideo ? _maxUsedHeight : _availableHeight;
if ((_width > usew) || (_height > useh) || _fullScreenVideo) { if ((_width > usew) || (_height > useh) || _fullScreenVideo) {
const auto use = _fullScreenVideo ? _zoomToScreen : _zoomToDefault; const auto use = _fullScreenVideo ? _zoomToScreen : _zoomToDefault;
_zoom = kZoomToScreenLevel; _zoom = kZoomToScreenLevel;
@ -3156,6 +3203,10 @@ void OverlayWidget::show(OpenRequest request) {
} }
} }
} }
if (isHidden() || isMinimized()) {
// Count top notch on macOS before counting geometry.
_helper->beforeShow(_fullscreen);
}
if (photo) { if (photo) {
if (contextItem && contextPeer) { if (contextItem && contextPeer) {
return; return;
@ -4240,6 +4291,14 @@ void OverlayWidget::storiesVolumeChangeFinished() {
playbackControlsVolumeChangeFinished(); playbackControlsVolumeChangeFinished();
} }
int OverlayWidget::topNotchSkip() const {
return _fullscreen ? _topNotchSize : 0;
}
int OverlayWidget::storiesTopNotchSkip() {
return topNotchSkip();
}
void OverlayWidget::playbackToggleFullScreen() { void OverlayWidget::playbackToggleFullScreen() {
Expects(_streamed != nullptr); Expects(_streamed != nullptr);
@ -5366,7 +5425,7 @@ bool OverlayWidget::handleDoubleClick(
void OverlayWidget::snapXY() { void OverlayWidget::snapXY() {
auto xmin = width() - _w, xmax = 0; auto xmin = width() - _w, xmax = 0;
auto ymin = height() - _h, ymax = 0; auto ymin = height() - _h, ymax = _minUsedTop;
accumulate_min(xmin, (width() - _w) / 2); accumulate_min(xmin, (width() - _w) / 2);
accumulate_max(xmax, (width() - _w) / 2); accumulate_max(xmax, (width() - _w) / 2);
accumulate_min(ymin, _skipTop + (_availableHeight - _h) / 2); accumulate_min(ymin, _skipTop + (_availableHeight - _h) / 2);
@ -5390,7 +5449,7 @@ void OverlayWidget::handleMouseMove(QPoint position) {
>= QApplication::startDragDistance())) { >= QApplication::startDragDistance())) {
_dragging = QRect(_x, _y, _w, _h).contains(_mStart) ? 1 : -1; _dragging = QRect(_x, _y, _w, _h).contains(_mStart) ? 1 : -1;
if (_dragging > 0) { if (_dragging > 0) {
if (_w > width() || _h > height()) { if (_w > width() || _h > _maxUsedHeight) {
setCursor(style::cur_sizeall); setCursor(style::cur_sizeall);
} else { } else {
setCursor(style::cur_default); setCursor(style::cur_default);

View file

@ -243,6 +243,7 @@ private:
void playbackResumeOnCall(); void playbackResumeOnCall();
void playbackPauseMusic(); void playbackPauseMusic();
void switchToPip(); void switchToPip();
[[nodiscard]] int topNotchSkip() const;
not_null<Ui::RpWidget*> storiesWrap() override; not_null<Ui::RpWidget*> storiesWrap() override;
std::shared_ptr<ChatHelpers::Show> storiesShow() override; std::shared_ptr<ChatHelpers::Show> storiesShow() override;
@ -264,6 +265,7 @@ private:
void storiesVolumeToggle() override; void storiesVolumeToggle() override;
void storiesVolumeChanged(float64 volume) override; void storiesVolumeChanged(float64 volume) override;
void storiesVolumeChangeFinished() override; void storiesVolumeChangeFinished() override;
int storiesTopNotchSkip() override;
void hideControls(bool force = false); void hideControls(bool force = false);
void subscribeToScreenGeometry(); void subscribeToScreenGeometry();
@ -589,10 +591,13 @@ private:
bool _captionFitsIfExpanded = false; bool _captionFitsIfExpanded = false;
bool _captionExpanded = false; bool _captionExpanded = false;
int _topNotchSize = 0;
int _width = 0; int _width = 0;
int _height = 0; int _height = 0;
int _skipTop = 0; int _skipTop = 0;
int _availableHeight = 0; int _availableHeight = 0;
int _minUsedTop = 0; // Geometry without top notch on macOS.
int _maxUsedHeight = 0;
int _x = 0, _y = 0, _w = 0, _h = 0; int _x = 0, _y = 0, _w = 0, _h = 0;
int _xStart = 0, _yStart = 0; int _xStart = 0, _yStart = 0;
int _zoom = 0; // < 0 - out, 0 - none, > 0 - in int _zoom = 0; // < 0 - out, 0 - none, > 0 - in

View file

@ -36,6 +36,7 @@ public:
void clearState() override; void clearState() override;
void setControlsOpacity(float64 opacity) override; void setControlsOpacity(float64 opacity) override;
rpl::producer<bool> controlsSideRightValue() override; rpl::producer<bool> controlsSideRightValue() override;
rpl::producer<int> topNotchSkipValue() override;
private: private:
using Control = Ui::Platform::TitleControl; using Control = Ui::Platform::TitleControl;

View file

@ -35,6 +35,7 @@ struct MacOverlayWidgetHelper::Data {
rpl::event_stream<> clearStateRequests; rpl::event_stream<> clearStateRequests;
bool anyOver = false; bool anyOver = false;
NSWindow * __weak native = nil; NSWindow * __weak native = nil;
rpl::variable<int> topNotchSkip;
}; };
MacOverlayWidgetHelper::MacOverlayWidgetHelper( MacOverlayWidgetHelper::MacOverlayWidgetHelper(
@ -96,6 +97,9 @@ void MacOverlayWidgetHelper::updateStyles(bool fullscreen) {
[window setTitleVisibility:NSWindowTitleHidden]; [window setTitleVisibility:NSWindowTitleHidden];
[window setTitlebarAppearsTransparent:YES]; [window setTitlebarAppearsTransparent:YES];
[window setStyleMask:[window styleMask] | NSWindowStyleMaskFullSizeContentView]; [window setStyleMask:[window styleMask] | NSWindowStyleMaskFullSizeContentView];
if (@available(macOS 12.0, *)) {
_data->topNotchSkip = [[window screen] safeAreaInsets].top;
}
} }
void MacOverlayWidgetHelper::refreshButtons(bool fullscreen) { void MacOverlayWidgetHelper::refreshButtons(bool fullscreen) {
@ -153,6 +157,10 @@ rpl::producer<bool> MacOverlayWidgetHelper::controlsSideRightValue() {
return rpl::single(false); return rpl::single(false);
} }
rpl::producer<int> MacOverlayWidgetHelper::topNotchSkipValue() {
return _data->topNotchSkip.value();
}
object_ptr<Ui::AbstractButton> MacOverlayWidgetHelper::create( object_ptr<Ui::AbstractButton> MacOverlayWidgetHelper::create(
not_null<QWidget*> parent, not_null<QWidget*> parent,
Control control) { Control control) {

View file

@ -58,6 +58,9 @@ public:
-> rpl::producer<not_null<QMouseEvent*>> { -> rpl::producer<not_null<QMouseEvent*>> {
return rpl::never<not_null<QMouseEvent*>>(); return rpl::never<not_null<QMouseEvent*>>();
} }
[[nodiscard]] virtual rpl::producer<int> topNotchSkipValue() {
return rpl::single(0);
}
}; };
[[nodiscard]] std::unique_ptr<OverlayWidgetHelper> CreateOverlayWidgetHelper( [[nodiscard]] std::unique_ptr<OverlayWidgetHelper> CreateOverlayWidgetHelper(