mirror of https://github.com/procxx/kepka.git
Fix window activations handling without event loop nesting.
This was causing an assertion violation in Ui::PostponeCall. - Add a generic Core::QtSignalProducer to convert Qt signals to rpl::producer. - Track event loop nesting inside QtSignalProducer. - Use QtSignalProducer for QWindow::activeChanged tracking.
This commit is contained in:
parent
41b2e7c9c7
commit
2bdce7dce6
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "core/application.h"
|
#include "core/application.h"
|
||||||
|
#include "core/qt_signal_producer.h"
|
||||||
#include "styles/style_chat_helpers.h"
|
#include "styles/style_chat_helpers.h"
|
||||||
|
|
||||||
namespace ChatHelpers {
|
namespace ChatHelpers {
|
||||||
|
@ -90,11 +91,13 @@ TabbedPanel::TabbedPanel(
|
||||||
});
|
});
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
macWindowDeactivateEvents(
|
||||||
connect(App::wnd()->windowHandle(), &QWindow::activeChanged, this, [=] {
|
) | rpl::filter([=] {
|
||||||
windowActiveChanged();
|
return !isHidden() && !preventAutoHide();
|
||||||
});
|
}) | rpl::start_with_next([=] {
|
||||||
}
|
hideAnimated();
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||||
|
|
||||||
hideChildren();
|
hideChildren();
|
||||||
|
@ -146,12 +149,6 @@ void TabbedPanel::updateContentHeight() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabbedPanel::windowActiveChanged() {
|
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden() && !preventAutoHide()) {
|
|
||||||
hideAnimated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TabbedPanel::paintEvent(QPaintEvent *e) {
|
void TabbedPanel::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,6 @@ private:
|
||||||
return !_selector;
|
return !_selector;
|
||||||
}
|
}
|
||||||
void showFromSelector();
|
void showFromSelector();
|
||||||
void windowActiveChanged();
|
|
||||||
|
|
||||||
style::margins innerPadding() const;
|
style::margins innerPadding() const;
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,9 @@ MainQueueProcessor::MainQueueProcessor() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
crl::wrap_main_queue([](void (*callable)(void*), void *argument) {
|
crl::wrap_main_queue([](void (*callable)(void*), void *argument) {
|
||||||
Sandbox::Instance().registerEnterFromEventLoop();
|
Sandbox::Instance().customEnterFromEventLoop([&] {
|
||||||
const auto wrap = Sandbox::Instance().createEventNestingLevel();
|
callable(argument);
|
||||||
callable(argument);
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
base::InitObservables(ProcessObservables);
|
base::InitObservables(ProcessObservables);
|
||||||
|
|
|
@ -80,4 +80,4 @@ void MediaActiveCache<Type>::check(Unload &&unload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Images
|
} // namespace Core
|
||||||
|
|
|
@ -16,6 +16,12 @@ class Application;
|
||||||
class Sandbox final
|
class Sandbox final
|
||||||
: public QApplication
|
: public QApplication
|
||||||
, private QAbstractNativeEventFilter {
|
, private QAbstractNativeEventFilter {
|
||||||
|
private:
|
||||||
|
auto createEventNestingLevel() {
|
||||||
|
incrementEventNestingLevel();
|
||||||
|
return gsl::finally([=] { decrementEventNestingLevel(); });
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Sandbox(not_null<Launcher*> launcher, int &argc, char **argv);
|
Sandbox(not_null<Launcher*> launcher, int &argc, char **argv);
|
||||||
|
|
||||||
|
@ -29,10 +35,12 @@ public:
|
||||||
|
|
||||||
void postponeCall(FnMut<void()> &&callable);
|
void postponeCall(FnMut<void()> &&callable);
|
||||||
bool notify(QObject *receiver, QEvent *e) override;
|
bool notify(QObject *receiver, QEvent *e) override;
|
||||||
void registerEnterFromEventLoop();
|
|
||||||
auto createEventNestingLevel() {
|
template <typename Callable>
|
||||||
incrementEventNestingLevel();
|
auto customEnterFromEventLoop(Callable &&callable) {
|
||||||
return gsl::finally([=] { decrementEventNestingLevel(); });
|
registerEnterFromEventLoop();
|
||||||
|
const auto wrap = createEventNestingLevel();
|
||||||
|
return callable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void activateWindowDelayed(not_null<QWidget*> widget);
|
void activateWindowDelayed(not_null<QWidget*> widget);
|
||||||
|
@ -65,6 +73,7 @@ private:
|
||||||
|
|
||||||
void closeApplication(); // will be done in aboutToQuit()
|
void closeApplication(); // will be done in aboutToQuit()
|
||||||
void checkForQuit(); // will be done in exec()
|
void checkForQuit(); // will be done in exec()
|
||||||
|
void registerEnterFromEventLoop();
|
||||||
void incrementEventNestingLevel();
|
void incrementEventNestingLevel();
|
||||||
void decrementEventNestingLevel();
|
void decrementEventNestingLevel();
|
||||||
bool nativeEventFilter(
|
bool nativeEventFilter(
|
||||||
|
|
|
@ -718,7 +718,10 @@ void Inner::onSwitchPm() {
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
Widget::Widget(QWidget *parent, not_null<Window::Controller*> controller) : TWidget(parent)
|
Widget::Widget(
|
||||||
|
QWidget *parent,
|
||||||
|
not_null<Window::Controller*> controller)
|
||||||
|
: RpWidget(parent)
|
||||||
, _controller(controller)
|
, _controller(controller)
|
||||||
, _contentMaxHeight(st::emojiPanMaxHeight)
|
, _contentMaxHeight(st::emojiPanMaxHeight)
|
||||||
, _contentHeight(_contentMaxHeight)
|
, _contentHeight(_contentMaxHeight)
|
||||||
|
@ -742,9 +745,12 @@ Widget::Widget(QWidget *parent, not_null<Window::Controller*> controller) : TWid
|
||||||
_inlineRequestTimer.setSingleShot(true);
|
_inlineRequestTimer.setSingleShot(true);
|
||||||
connect(&_inlineRequestTimer, SIGNAL(timeout()), this, SLOT(onInlineRequest()));
|
connect(&_inlineRequestTimer, SIGNAL(timeout()), this, SLOT(onInlineRequest()));
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
macWindowDeactivateEvents(
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
) | rpl::filter([=] {
|
||||||
}
|
return !isHidden();
|
||||||
|
}) | rpl::start_with_next([=] {
|
||||||
|
leaveEvent(nullptr);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
// Inner widget has OpaquePaintEvent attribute so it doesn't repaint on scroll.
|
// Inner widget has OpaquePaintEvent attribute so it doesn't repaint on scroll.
|
||||||
// But we should force it to repaint so that GIFs will continue to animate without update() calls.
|
// But we should force it to repaint so that GIFs will continue to animate without update() calls.
|
||||||
|
@ -795,12 +801,6 @@ void Widget::updateContentHeight() {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::onWndActiveChanged() {
|
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
|
|
||||||
leaveEvent(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::paintEvent(QPaintEvent *e) {
|
void Widget::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/twidget.h"
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/abstract_button.h"
|
#include "ui/abstract_button.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/effects/panel_animation.h"
|
#include "ui/effects/panel_animation.h"
|
||||||
|
@ -161,7 +161,7 @@ private:
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
class Widget : public TWidget, private MTP::Sender {
|
class Widget : public Ui::RpWidget, private MTP::Sender {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -192,8 +192,6 @@ protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onWndActiveChanged();
|
|
||||||
|
|
||||||
void onScroll();
|
void onScroll();
|
||||||
|
|
||||||
void onInlineRequest();
|
void onInlineRequest();
|
||||||
|
|
|
@ -106,7 +106,14 @@ void MainWindow::initHook() {
|
||||||
Platform::MainWindow::initHook();
|
Platform::MainWindow::initHook();
|
||||||
|
|
||||||
QCoreApplication::instance()->installEventFilter(this);
|
QCoreApplication::instance()->installEventFilter(this);
|
||||||
connect(windowHandle(), &QWindow::activeChanged, this, [this] { checkHistoryActivation(); }, Qt::QueuedConnection);
|
|
||||||
|
// Non-queued activeChanged handlers must use QtSignalProducer.
|
||||||
|
connect(
|
||||||
|
windowHandle(),
|
||||||
|
&QWindow::activeChanged,
|
||||||
|
this,
|
||||||
|
[=] { checkHistoryActivation(); },
|
||||||
|
Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::firstShow() {
|
void MainWindow::firstShow() {
|
||||||
|
|
|
@ -54,12 +54,6 @@ bool Panel::overlaps(const QRect &globalRect) {
|
||||||
return rect().marginsRemoved(QMargins(marginLeft, contentTop(), marginRight, contentBottom())).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
return rect().marginsRemoved(QMargins(marginLeft, contentTop(), marginRight, contentBottom())).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::windowActiveChanged() {
|
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
|
|
||||||
leaveEvent(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Panel::resizeEvent(QResizeEvent *e) {
|
void Panel::resizeEvent(QResizeEvent *e) {
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
}
|
}
|
||||||
|
@ -173,7 +167,7 @@ void Panel::enterEventHook(QEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
_showTimer.callOnce(0);
|
_showTimer.callOnce(0);
|
||||||
}
|
}
|
||||||
return TWidget::enterEventHook(e);
|
return RpWidget::enterEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::leaveEventHook(QEvent *e) {
|
void Panel::leaveEventHook(QEvent *e) {
|
||||||
|
@ -186,7 +180,7 @@ void Panel::leaveEventHook(QEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
_hideTimer.callOnce(300);
|
_hideTimer.callOnce(300);
|
||||||
}
|
}
|
||||||
return TWidget::leaveEventHook(e);
|
return RpWidget::leaveEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::showFromOther() {
|
void Panel::showFromOther() {
|
||||||
|
@ -217,15 +211,12 @@ void Panel::ensureCreated() {
|
||||||
});
|
});
|
||||||
refreshList();
|
refreshList();
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
macWindowDeactivateEvents(
|
||||||
if (const auto window = App::wnd()) {
|
) | rpl::filter([=] {
|
||||||
connect(
|
return !isHidden();
|
||||||
window->windowHandle(),
|
}) | rpl::start_with_next([=] {
|
||||||
&QWindow::activeChanged,
|
leaveEvent(nullptr);
|
||||||
this,
|
}, _refreshListLifetime);
|
||||||
&Panel::windowActiveChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ignoringEnterEvents = false;
|
_ignoringEnterEvents = false;
|
||||||
}
|
}
|
||||||
|
@ -306,16 +297,6 @@ void Panel::performDestroy() {
|
||||||
_scroll->takeWidget<QWidget>().destroy();
|
_scroll->takeWidget<QWidget>().destroy();
|
||||||
_listPeer = _listMigratedPeer = nullptr;
|
_listPeer = _listMigratedPeer = nullptr;
|
||||||
_refreshListLifetime.destroy();
|
_refreshListLifetime.destroy();
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
|
||||||
if (const auto window = App::wnd()) {
|
|
||||||
disconnect(
|
|
||||||
window->windowHandle(),
|
|
||||||
&QWindow::activeChanged,
|
|
||||||
this,
|
|
||||||
&Panel::windowActiveChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Info::Key Panel::key() const {
|
Info::Key Panel::key() const {
|
||||||
|
|
|
@ -60,7 +60,6 @@ private:
|
||||||
void listHeightUpdated(int newHeight);
|
void listHeightUpdated(int newHeight);
|
||||||
int emptyInnerHeight() const;
|
int emptyInnerHeight() const;
|
||||||
bool contentTooSmall() const;
|
bool contentTooSmall() const;
|
||||||
void windowActiveChanged();
|
|
||||||
|
|
||||||
void ensureCreated();
|
void ensureCreated();
|
||||||
void performDestroy();
|
void performDestroy();
|
||||||
|
|
|
@ -19,7 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Media {
|
namespace Media {
|
||||||
namespace Player {
|
namespace Player {
|
||||||
|
|
||||||
VolumeController::VolumeController(QWidget *parent) : TWidget(parent)
|
VolumeController::VolumeController(QWidget *parent)
|
||||||
|
: TWidget(parent)
|
||||||
, _slider(this, st::mediaPlayerPanelPlayback) {
|
, _slider(this, st::mediaPlayerPanelPlayback) {
|
||||||
_slider->setMoveByWheel(true);
|
_slider->setMoveByWheel(true);
|
||||||
_slider->setChangeProgressCallback([this](float64 volume) {
|
_slider->setChangeProgressCallback([this](float64 volume) {
|
||||||
|
@ -68,7 +69,8 @@ void VolumeController::applyVolumeChange(float64 volume) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeWidget::VolumeWidget(QWidget *parent) : TWidget(parent)
|
VolumeWidget::VolumeWidget(QWidget *parent)
|
||||||
|
: RpWidget(parent)
|
||||||
, _controller(this) {
|
, _controller(this) {
|
||||||
hide();
|
hide();
|
||||||
_controller->setIsVertical(true);
|
_controller->setIsVertical(true);
|
||||||
|
@ -79,9 +81,12 @@ VolumeWidget::VolumeWidget(QWidget *parent) : TWidget(parent)
|
||||||
_showTimer.setSingleShot(true);
|
_showTimer.setSingleShot(true);
|
||||||
connect(&_showTimer, SIGNAL(timeout()), this, SLOT(onShowStart()));
|
connect(&_showTimer, SIGNAL(timeout()), this, SLOT(onShowStart()));
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
macWindowDeactivateEvents(
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()));
|
) | rpl::filter([=] {
|
||||||
}
|
return !isHidden();
|
||||||
|
}) | rpl::start_with_next([=] {
|
||||||
|
leaveEvent(nullptr);
|
||||||
|
}, lifetime());
|
||||||
|
|
||||||
hide();
|
hide();
|
||||||
auto margin = getMargin();
|
auto margin = getMargin();
|
||||||
|
@ -102,12 +107,6 @@ bool VolumeWidget::overlaps(const QRect &globalRect) {
|
||||||
return rect().marginsRemoved(getMargin()).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
return rect().marginsRemoved(getMargin()).contains(QRect(mapFromGlobal(globalRect.topLeft()), globalRect.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeWidget::onWindowActiveChanged() {
|
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
|
|
||||||
leaveEvent(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VolumeWidget::resizeEvent(QResizeEvent *e) {
|
void VolumeWidget::resizeEvent(QResizeEvent *e) {
|
||||||
auto inner = rect().marginsRemoved(getMargin());
|
auto inner = rect().marginsRemoved(getMargin());
|
||||||
_controller->setGeometry(inner.x(), inner.y() - st::lineWidth, inner.width(), inner.height() + st::lineWidth - ((st::mediaPlayerVolumeSize.width() - st::mediaPlayerPanelPlayback.width) / 2));
|
_controller->setGeometry(inner.x(), inner.y() - st::lineWidth, inner.width(), inner.height() + st::lineWidth - ((st::mediaPlayerVolumeSize.width() - st::mediaPlayerPanelPlayback.width) / 2));
|
||||||
|
@ -147,7 +146,7 @@ void VolumeWidget::enterEventHook(QEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
_showTimer.start(0);
|
_showTimer.start(0);
|
||||||
}
|
}
|
||||||
return TWidget::enterEventHook(e);
|
return RpWidget::enterEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeWidget::leaveEventHook(QEvent *e) {
|
void VolumeWidget::leaveEventHook(QEvent *e) {
|
||||||
|
@ -157,7 +156,7 @@ void VolumeWidget::leaveEventHook(QEvent *e) {
|
||||||
} else {
|
} else {
|
||||||
_hideTimer.start(300);
|
_hideTimer.start(300);
|
||||||
}
|
}
|
||||||
return TWidget::leaveEventHook(e);
|
return RpWidget::leaveEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VolumeWidget::otherEnter() {
|
void VolumeWidget::otherEnter() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class IconButton;
|
class IconButton;
|
||||||
|
@ -34,7 +35,7 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VolumeWidget : public TWidget {
|
class VolumeWidget : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -55,7 +56,6 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
void onShowStart();
|
void onShowStart();
|
||||||
void onHideStart();
|
void onHideStart();
|
||||||
void onWindowActiveChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void otherEnter();
|
void otherEnter();
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <rpl/map.h>
|
#include <rpl/map.h>
|
||||||
#include <rpl/distinct_until_changed.h>
|
#include <rpl/distinct_until_changed.h>
|
||||||
#include "base/unique_qptr.h"
|
#include "base/unique_qptr.h"
|
||||||
|
#include "core/qt_signal_producer.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace details {
|
namespace details {
|
||||||
|
@ -173,6 +174,25 @@ public:
|
||||||
visibilityChangedHook(wasVisible, !this->isHidden());
|
visibilityChangedHook(wasVisible, !this->isHidden());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto windowDeactivateEvents() const {
|
||||||
|
Expects(Widget::window()->windowHandle() != nullptr);
|
||||||
|
|
||||||
|
const auto window = Widget::window()->windowHandle();
|
||||||
|
return Core::QtSignalProducer(
|
||||||
|
window,
|
||||||
|
&QWindow::activeChanged
|
||||||
|
) | rpl::filter([=] {
|
||||||
|
return !window->isActive();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto macWindowDeactivateEvents() const {
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
return windowDeactivateEvents();
|
||||||
|
#else // Q_OS_MAC
|
||||||
|
return rpl::never<rpl::empty_value>();
|
||||||
|
#endif // Q_OS_MAC
|
||||||
|
}
|
||||||
|
|
||||||
~RpWidgetWrap() {
|
~RpWidgetWrap() {
|
||||||
base::take(_lifetime);
|
base::take(_lifetime);
|
||||||
base::take(_eventStreams);
|
base::take(_eventStreams);
|
||||||
|
|
|
@ -22,7 +22,10 @@ constexpr int kFadeAlphaMax = 160;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st) : TWidget(parent)
|
InnerDropdown::InnerDropdown(
|
||||||
|
QWidget *parent,
|
||||||
|
const style::InnerDropdown &st)
|
||||||
|
: RpWidget(parent)
|
||||||
, _st(st)
|
, _st(st)
|
||||||
, _scroll(this, _st.scroll) {
|
, _scroll(this, _st.scroll) {
|
||||||
_hideTimer.setSingleShot(true);
|
_hideTimer.setSingleShot(true);
|
||||||
|
@ -30,11 +33,21 @@ InnerDropdown::InnerDropdown(QWidget *parent, const style::InnerDropdown &st) :
|
||||||
|
|
||||||
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
connect(_scroll, SIGNAL(scrolled()), this, SLOT(onScroll()));
|
||||||
|
|
||||||
if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
|
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWindowActiveChanged()));
|
|
||||||
}
|
|
||||||
|
|
||||||
hide();
|
hide();
|
||||||
|
|
||||||
|
shownValue(
|
||||||
|
) | rpl::filter([](bool shown) {
|
||||||
|
return shown;
|
||||||
|
}) | rpl::take(1) | rpl::map([=] {
|
||||||
|
// We can't invoke this before the window is created.
|
||||||
|
// So instead we start handling them on the first show().
|
||||||
|
return macWindowDeactivateEvents();
|
||||||
|
}) | rpl::flatten_latest(
|
||||||
|
) | rpl::filter([=] {
|
||||||
|
return !isHidden();
|
||||||
|
}) | rpl::start_with_next([=] {
|
||||||
|
leaveEvent(nullptr);
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointer<TWidget> InnerDropdown::doSetOwnedWidget(object_ptr<TWidget> widget) {
|
QPointer<TWidget> InnerDropdown::doSetOwnedWidget(object_ptr<TWidget> widget) {
|
||||||
|
@ -71,12 +84,6 @@ void InnerDropdown::resizeToContent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::onWindowActiveChanged() {
|
|
||||||
if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
|
|
||||||
leaveEvent(nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void InnerDropdown::resizeEvent(QResizeEvent *e) {
|
void InnerDropdown::resizeEvent(QResizeEvent *e) {
|
||||||
_scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin));
|
_scroll->setGeometry(rect().marginsRemoved(_st.padding).marginsRemoved(_st.scrollMargin));
|
||||||
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
|
if (auto widget = static_cast<TWidget*>(_scroll->widget())) {
|
||||||
|
@ -124,7 +131,7 @@ void InnerDropdown::enterEventHook(QEvent *e) {
|
||||||
if (_autoHiding) {
|
if (_autoHiding) {
|
||||||
showAnimated(_origin);
|
showAnimated(_origin);
|
||||||
}
|
}
|
||||||
return TWidget::enterEventHook(e);
|
return RpWidget::enterEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::leaveEventHook(QEvent *e) {
|
void InnerDropdown::leaveEventHook(QEvent *e) {
|
||||||
|
@ -135,7 +142,7 @@ void InnerDropdown::leaveEventHook(QEvent *e) {
|
||||||
_hideTimer.start(300);
|
_hideTimer.start(300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TWidget::leaveEventHook(e);
|
return RpWidget::leaveEventHook(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InnerDropdown::otherEnter() {
|
void InnerDropdown::otherEnter() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "styles/style_widgets.h"
|
#include "styles/style_widgets.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/effects/panel_animation.h"
|
#include "ui/effects/panel_animation.h"
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ namespace Ui {
|
||||||
|
|
||||||
class ScrollArea;
|
class ScrollArea;
|
||||||
|
|
||||||
class InnerDropdown : public TWidget {
|
class InnerDropdown : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -81,7 +82,6 @@ private slots:
|
||||||
void onHideAnimated() {
|
void onHideAnimated() {
|
||||||
hideAnimated();
|
hideAnimated();
|
||||||
}
|
}
|
||||||
void onWindowActiveChanged();
|
|
||||||
void onScroll();
|
void onScroll();
|
||||||
void onWidgetHeightUpdated() {
|
void onWidgetHeightUpdated() {
|
||||||
resizeToContent();
|
resizeToContent();
|
||||||
|
|
|
@ -8,8 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/widgets/tooltip.h"
|
#include "ui/widgets/tooltip.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "styles/style_widgets.h"
|
|
||||||
#include "platform/platform_specific.h"
|
#include "platform/platform_specific.h"
|
||||||
|
#include "core/qt_signal_producer.h"
|
||||||
|
#include "styles/style_widgets.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ AbstractTooltipShower::~AbstractTooltipShower() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Tooltip::Tooltip() : TWidget(nullptr) {
|
Tooltip::Tooltip() : RpWidget(nullptr) {
|
||||||
TooltipInstance = this;
|
TooltipInstance = this;
|
||||||
|
|
||||||
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::ToolTip);
|
setWindowFlags(Qt::WindowFlags(Qt::FramelessWindowHint) | Qt::BypassWindowManagerHint | Qt::NoDropShadowWindowHint | Qt::ToolTip);
|
||||||
|
@ -43,7 +44,10 @@ Tooltip::Tooltip() : TWidget(nullptr) {
|
||||||
_showTimer.setCallback([=] { performShow(); });
|
_showTimer.setCallback([=] { performShow(); });
|
||||||
_hideByLeaveTimer.setCallback([=] { Hide(); });
|
_hideByLeaveTimer.setCallback([=] { Hide(); });
|
||||||
|
|
||||||
connect(App::wnd()->windowHandle(), SIGNAL(activeChanged()), this, SLOT(onWndActiveChanged()));
|
App::wnd()->windowDeactivateEvents(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
Hide();
|
||||||
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tooltip::performShow() {
|
void Tooltip::performShow() {
|
||||||
|
@ -57,12 +61,6 @@ void Tooltip::performShow() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tooltip::onWndActiveChanged() {
|
|
||||||
if (!App::wnd() || !App::wnd()->windowHandle() || !App::wnd()->windowHandle()->isActive()) {
|
|
||||||
Hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Tooltip::eventFilter(QObject *o, QEvent *e) {
|
bool Tooltip::eventFilter(QObject *o, QEvent *e) {
|
||||||
if (e->type() == QEvent::Leave) {
|
if (e->type() == QEvent::Leave) {
|
||||||
_hideByLeaveTimer.callOnce(10);
|
_hideByLeaveTimer.callOnce(10);
|
||||||
|
@ -73,7 +71,7 @@ bool Tooltip::eventFilter(QObject *o, QEvent *e) {
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TWidget::eventFilter(o, e);
|
return RpWidget::eventFilter(o, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Tooltip::~Tooltip() {
|
Tooltip::~Tooltip() {
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
#include "ui/effects/animations.h"
|
#include "ui/effects/animations.h"
|
||||||
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
struct Tooltip;
|
struct Tooltip;
|
||||||
|
@ -27,16 +28,11 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Tooltip : public TWidget {
|
class Tooltip : public Ui::RpWidget {
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Show(int32 delay, const AbstractTooltipShower *shower);
|
static void Show(int32 delay, const AbstractTooltipShower *shower);
|
||||||
static void Hide();
|
static void Hide();
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onWndActiveChanged();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void hideEvent(QHideEvent *e) override;
|
void hideEvent(QHideEvent *e) override;
|
||||||
|
|
|
@ -273,8 +273,18 @@ void MainWindow::init() {
|
||||||
initHook();
|
initHook();
|
||||||
updateWindowIcon();
|
updateWindowIcon();
|
||||||
|
|
||||||
connect(windowHandle(), &QWindow::activeChanged, this, [this] { handleActiveChanged(); }, Qt::QueuedConnection);
|
// Non-queued activeChanged handlers must use QtSignalProducer.
|
||||||
connect(windowHandle(), &QWindow::windowStateChanged, this, [this](Qt::WindowState state) { handleStateChanged(state); });
|
connect(
|
||||||
|
windowHandle(),
|
||||||
|
&QWindow::activeChanged,
|
||||||
|
this,
|
||||||
|
[=] { handleActiveChanged(); },
|
||||||
|
Qt::QueuedConnection);
|
||||||
|
connect(
|
||||||
|
windowHandle(),
|
||||||
|
&QWindow::windowStateChanged,
|
||||||
|
this,
|
||||||
|
[=](Qt::WindowState state) { handleStateChanged(state); });
|
||||||
|
|
||||||
updatePalette();
|
updatePalette();
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "support/support_templates.h"
|
#include "support/support_templates.h"
|
||||||
#include "settings/settings_common.h"
|
#include "settings/settings_common.h"
|
||||||
|
#include "core/qt_signal_producer.h"
|
||||||
#include "boxes/about_box.h"
|
#include "boxes/about_box.h"
|
||||||
#include "boxes/peer_list_controllers.h"
|
#include "boxes/peer_list_controllers.h"
|
||||||
#include "calls/calls_box_controller.h"
|
#include "calls/calls_box_controller.h"
|
||||||
|
@ -33,32 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace {
|
|
||||||
|
|
||||||
template <typename Object, typename Other, typename Value>
|
|
||||||
auto qtSignalProducer(
|
|
||||||
Object *object,
|
|
||||||
void(Other::*signal)(Value)) {
|
|
||||||
using Produced = std::remove_const_t<std::decay_t<Value>>;
|
|
||||||
const auto guarded = make_weak(object);
|
|
||||||
return rpl::make_producer<Produced>([=](auto consumer) {
|
|
||||||
if (!guarded) {
|
|
||||||
return rpl::lifetime();
|
|
||||||
}
|
|
||||||
auto listener = Ui::CreateChild<QObject>(guarded.data());
|
|
||||||
QObject::connect(guarded, signal, listener, [=](Value value) {
|
|
||||||
consumer.put_next_copy(value);
|
|
||||||
});
|
|
||||||
const auto weak = make_weak(listener);
|
|
||||||
return rpl::lifetime([=] {
|
|
||||||
if (weak) {
|
|
||||||
delete weak;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
class MainMenu::ResetScaleButton : public Ui::AbstractButton {
|
class MainMenu::ResetScaleButton : public Ui::AbstractButton {
|
||||||
public:
|
public:
|
||||||
|
@ -311,15 +286,15 @@ void MainMenu::initResetScaleButton() {
|
||||||
rpl::single(
|
rpl::single(
|
||||||
handle->screen()
|
handle->screen()
|
||||||
) | rpl::then(
|
) | rpl::then(
|
||||||
qtSignalProducer(handle, &QWindow::screenChanged)
|
Core::QtSignalProducer(handle, &QWindow::screenChanged)
|
||||||
) | rpl::map([](QScreen *screen) {
|
) | rpl::map([](QScreen *screen) {
|
||||||
return rpl::single(
|
return rpl::single(
|
||||||
screen->availableGeometry()
|
screen->availableGeometry()
|
||||||
) | rpl::then(
|
) | rpl::then(
|
||||||
#ifdef OS_MAC_OLD
|
#ifdef OS_MAC_OLD
|
||||||
qtSignalProducer(screen, &QScreen::virtualGeometryChanged)
|
Core::QtSignalProducer(screen, &QScreen::virtualGeometryChanged)
|
||||||
#else // OS_MAC_OLD
|
#else // OS_MAC_OLD
|
||||||
qtSignalProducer(screen, &QScreen::availableGeometryChanged)
|
Core::QtSignalProducer(screen, &QScreen::availableGeometryChanged)
|
||||||
#endif // OS_MAC_OLD
|
#endif // OS_MAC_OLD
|
||||||
);
|
);
|
||||||
}) | rpl::flatten_latest(
|
}) | rpl::flatten_latest(
|
||||||
|
|
|
@ -146,6 +146,7 @@
|
||||||
<(src_loc)/core/media_active_cache.h
|
<(src_loc)/core/media_active_cache.h
|
||||||
<(src_loc)/core/mime_type.cpp
|
<(src_loc)/core/mime_type.cpp
|
||||||
<(src_loc)/core/mime_type.h
|
<(src_loc)/core/mime_type.h
|
||||||
|
<(src_loc)/core/qt_signal_producer.h
|
||||||
<(src_loc)/core/sandbox.cpp
|
<(src_loc)/core/sandbox.cpp
|
||||||
<(src_loc)/core/sandbox.h
|
<(src_loc)/core/sandbox.h
|
||||||
<(src_loc)/core/shortcuts.cpp
|
<(src_loc)/core/shortcuts.cpp
|
||||||
|
|
Loading…
Reference in New Issue