Updated lib_ui sources to TDesktop version 2.7.2
This commit is contained in:
commit
545a792033
20 changed files with 462 additions and 91 deletions
|
|
@ -211,8 +211,6 @@ PRIVATE
|
||||||
ui/round_rect.h
|
ui/round_rect.h
|
||||||
ui/rp_widget.cpp
|
ui/rp_widget.cpp
|
||||||
ui/rp_widget.h
|
ui/rp_widget.h
|
||||||
ui/ui_log.cpp
|
|
||||||
ui/ui_log.h
|
|
||||||
ui/ui_utility.cpp
|
ui/ui_utility.cpp
|
||||||
ui/ui_utility.h
|
ui/ui_utility.h
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
#include "base/bytes.h"
|
#include "base/bytes.h"
|
||||||
#include "base/openssl_help.h"
|
#include "base/openssl_help.h"
|
||||||
#include "base/parse_helper.h"
|
#include "base/parse_helper.h"
|
||||||
|
#include "base/debug_log.h"
|
||||||
#include "ui/style/style_core.h"
|
#include "ui/style/style_core.h"
|
||||||
#include "ui/painter.h"
|
#include "ui/painter.h"
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
#include "ui/ui_log.h"
|
|
||||||
#include "styles/style_basic.h"
|
#include "styles/style_basic.h"
|
||||||
|
|
||||||
#include <QtCore/QJsonDocument>
|
#include <QtCore/QJsonDocument>
|
||||||
|
|
@ -218,7 +218,7 @@ void SaveToFile(int id, const QImage &image, int size, int index) {
|
||||||
if (!f.open(QIODevice::WriteOnly)) {
|
if (!f.open(QIODevice::WriteOnly)) {
|
||||||
if (!QDir::current().mkpath(internal::CacheFileFolder())
|
if (!QDir::current().mkpath(internal::CacheFileFolder())
|
||||||
|| !f.open(QIODevice::WriteOnly)) {
|
|| !f.open(QIODevice::WriteOnly)) {
|
||||||
UI_LOG(("App Error: Could not open emoji cache '%1' for size %2_%3"
|
LOG(("App Error: Could not open emoji cache '%1' for size %2_%3"
|
||||||
).arg(f.fileName()
|
).arg(f.fileName()
|
||||||
).arg(size
|
).arg(size
|
||||||
).arg(index));
|
).arg(index));
|
||||||
|
|
@ -244,7 +244,7 @@ void SaveToFile(int id, const QImage &image, int size, int index) {
|
||||||
|| !write(data)
|
|| !write(data)
|
||||||
|| !write(openssl::Sha256(bytes::make_span(header), data))
|
|| !write(openssl::Sha256(bytes::make_span(header), data))
|
||||||
|| false) {
|
|| false) {
|
||||||
UI_LOG(("App Error: Could not write emoji cache '%1' for size %2"
|
LOG(("App Error: Could not write emoji cache '%1' for size %2"
|
||||||
).arg(f.fileName()
|
).arg(f.fileName()
|
||||||
).arg(size));
|
).arg(size));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,12 +36,6 @@ void Integration::textActionsUpdated() {
|
||||||
void Integration::activationFromTopPanel() {
|
void Integration::activationFromTopPanel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Integration::startFontsBegin() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Integration::startFontsEnd() {
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Integration::timeFormat() {
|
QString Integration::timeFormat() {
|
||||||
return u"hh:mm"_q;
|
return u"hh:mm"_q;
|
||||||
}
|
}
|
||||||
|
|
@ -79,10 +73,6 @@ const Emoji::One *Integration::defaultEmojiVariant(const Emoji::One *emoji) {
|
||||||
return emoji;
|
return emoji;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *Integration::modalWindowParent() {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpl::producer<> Integration::forcePopupMenuHideRequests() {
|
rpl::producer<> Integration::forcePopupMenuHideRequests() {
|
||||||
return rpl::never<rpl::empty_value>();
|
return rpl::never<rpl::empty_value>();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,15 +35,11 @@ public:
|
||||||
virtual void registerLeaveSubscription(not_null<QWidget*> widget) = 0;
|
virtual void registerLeaveSubscription(not_null<QWidget*> widget) = 0;
|
||||||
virtual void unregisterLeaveSubscription(not_null<QWidget*> widget) = 0;
|
virtual void unregisterLeaveSubscription(not_null<QWidget*> widget) = 0;
|
||||||
|
|
||||||
virtual void writeLogEntry(const QString &entry) = 0;
|
|
||||||
[[nodiscard]] virtual QString emojiCacheFolder() = 0;
|
[[nodiscard]] virtual QString emojiCacheFolder() = 0;
|
||||||
|
|
||||||
virtual void textActionsUpdated();
|
virtual void textActionsUpdated();
|
||||||
virtual void activationFromTopPanel();
|
virtual void activationFromTopPanel();
|
||||||
|
|
||||||
virtual void startFontsBegin();
|
|
||||||
virtual void startFontsEnd();
|
|
||||||
|
|
||||||
[[nodiscard]] virtual QString timeFormat();
|
[[nodiscard]] virtual QString timeFormat();
|
||||||
|
|
||||||
[[nodiscard]] virtual std::shared_ptr<ClickHandler> createLinkHandler(
|
[[nodiscard]] virtual std::shared_ptr<ClickHandler> createLinkHandler(
|
||||||
|
|
@ -56,8 +52,6 @@ public:
|
||||||
[[nodiscard]] virtual const Emoji::One *defaultEmojiVariant(
|
[[nodiscard]] virtual const Emoji::One *defaultEmojiVariant(
|
||||||
const Emoji::One *emoji);
|
const Emoji::One *emoji);
|
||||||
|
|
||||||
[[nodiscard]] virtual QWidget *modalWindowParent();
|
|
||||||
|
|
||||||
[[nodiscard]] virtual rpl::producer<> forcePopupMenuHideRequests();
|
[[nodiscard]] virtual rpl::producer<> forcePopupMenuHideRequests();
|
||||||
|
|
||||||
[[nodiscard]] virtual QString phraseContextCopyText();
|
[[nodiscard]] virtual QString phraseContextCopyText();
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace Ui {
|
||||||
void GenericBox::prepare() {
|
void GenericBox::prepare() {
|
||||||
_init(this);
|
_init(this);
|
||||||
|
|
||||||
auto wrap = object_ptr<Ui::OverrideMargins>(this, std::move(_content));
|
auto wrap = object_ptr<Ui::OverrideMargins>(this, std::move(_owned));
|
||||||
setDimensionsToContent(_width ? _width : st::boxWidth, wrap.data());
|
setDimensionsToContent(_width ? _width : st::boxWidth, wrap.data());
|
||||||
setInnerWidget(std::move(wrap));
|
setInnerWidget(std::move(wrap));
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ void GenericBox::addSkip(int height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<Ui::VerticalLayout*> GenericBox::verticalLayout() {
|
not_null<Ui::VerticalLayout*> GenericBox::verticalLayout() {
|
||||||
return _content.data();
|
return _content;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,8 @@ private:
|
||||||
FnMut<void(not_null<GenericBox*>)> _init;
|
FnMut<void(not_null<GenericBox*>)> _init;
|
||||||
Fn<void()> _focus;
|
Fn<void()> _focus;
|
||||||
Fn<void()> _showFinished;
|
Fn<void()> _showFinished;
|
||||||
object_ptr<Ui::VerticalLayout> _content;
|
object_ptr<Ui::VerticalLayout> _owned;
|
||||||
|
not_null<Ui::VerticalLayout*> _content;
|
||||||
int _width = 0;
|
int _width = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -166,7 +167,8 @@ inline GenericBox::GenericBox(
|
||||||
MakeIniter(
|
MakeIniter(
|
||||||
std::forward<InitMethod>(init),
|
std::forward<InitMethod>(init),
|
||||||
std::forward<InitArgs>(args)...))
|
std::forward<InitArgs>(args)...))
|
||||||
, _content(this) {
|
, _owned(this)
|
||||||
|
, _content(_owned.data()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
//
|
//
|
||||||
#include "ui/platform/linux/ui_utility_linux.h"
|
#include "ui/platform/linux/ui_utility_linux.h"
|
||||||
|
|
||||||
#include "ui/ui_log.h"
|
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "base/platform/linux/base_linux_gtk_integration.h"
|
#include "base/platform/linux/base_linux_gtk_integration.h"
|
||||||
|
#include "base/debug_log.h"
|
||||||
#include "ui/platform/linux/ui_linux_wayland_integration.h"
|
#include "ui/platform/linux/ui_linux_wayland_integration.h"
|
||||||
#include "base/const_string.h"
|
#include "base/const_string.h"
|
||||||
#include "base/qt_adapters.h"
|
#include "base/qt_adapters.h"
|
||||||
|
|
@ -33,6 +33,259 @@ namespace {
|
||||||
constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs;
|
constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs;
|
||||||
|
|
||||||
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||||
|
std::optional<bool> XCBWindowMapped(xcb_window_t window) {
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_get_window_attributes(connection, window);
|
||||||
|
const auto reply = xcb_get_window_attributes_reply(
|
||||||
|
connection,
|
||||||
|
cookie,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
return reply->map_state == XCB_MAP_STATE_VIEWABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> XCBWindowHidden(xcb_window_t window) {
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto stateAtom = base::Platform::XCB::GetAtom(
|
||||||
|
connection,
|
||||||
|
"_NET_WM_STATE");
|
||||||
|
|
||||||
|
const auto stateHiddenAtom = base::Platform::XCB::GetAtom(
|
||||||
|
connection,
|
||||||
|
"_NET_WM_STATE_HIDDEN");
|
||||||
|
|
||||||
|
if (!stateAtom.has_value() || !stateHiddenAtom.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_get_property(
|
||||||
|
connection,
|
||||||
|
false,
|
||||||
|
window,
|
||||||
|
*stateAtom,
|
||||||
|
XCB_ATOM_ATOM,
|
||||||
|
0,
|
||||||
|
1024);
|
||||||
|
|
||||||
|
const auto reply = xcb_get_property_reply(
|
||||||
|
connection,
|
||||||
|
cookie,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
if (reply->type != XCB_ATOM_ATOM || reply->format != 32) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto atomsStart = reinterpret_cast<xcb_atom_t*>(
|
||||||
|
xcb_get_property_value(reply));
|
||||||
|
|
||||||
|
const auto states = std::vector<xcb_atom_t>(
|
||||||
|
atomsStart,
|
||||||
|
atomsStart + reply->length);
|
||||||
|
|
||||||
|
return ranges::contains(states, *stateHiddenAtom);
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect XCBWindowGeometry(xcb_window_t window) {
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_get_geometry(connection, window);
|
||||||
|
const auto reply = xcb_get_geometry_reply(
|
||||||
|
connection,
|
||||||
|
cookie,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
return QRect(reply->x, reply->y, reply->width, reply->height);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint> XCBCurrentWorkspace() {
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto root = base::Platform::XCB::GetRootWindowFromQt();
|
||||||
|
if (!root.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto currentDesktopAtom = base::Platform::XCB::GetAtom(
|
||||||
|
connection,
|
||||||
|
"_NET_CURRENT_DESKTOP");
|
||||||
|
|
||||||
|
if (!currentDesktopAtom.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_get_property(
|
||||||
|
connection,
|
||||||
|
false,
|
||||||
|
*root,
|
||||||
|
*currentDesktopAtom,
|
||||||
|
XCB_ATOM_CARDINAL,
|
||||||
|
0,
|
||||||
|
1024);
|
||||||
|
|
||||||
|
const auto reply = xcb_get_property_reply(
|
||||||
|
connection,
|
||||||
|
cookie,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
return (reply->type == XCB_ATOM_CARDINAL)
|
||||||
|
? std::make_optional(
|
||||||
|
*reinterpret_cast<ulong*>(xcb_get_property_value(reply)))
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<uint> XCBWindowWorkspace(xcb_window_t window) {
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto desktopAtom = base::Platform::XCB::GetAtom(
|
||||||
|
connection,
|
||||||
|
"_NET_WM_DESKTOP");
|
||||||
|
|
||||||
|
if (!desktopAtom.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_get_property(
|
||||||
|
connection,
|
||||||
|
false,
|
||||||
|
window,
|
||||||
|
*desktopAtom,
|
||||||
|
XCB_ATOM_CARDINAL,
|
||||||
|
0,
|
||||||
|
1024);
|
||||||
|
|
||||||
|
const auto reply = xcb_get_property_reply(
|
||||||
|
connection,
|
||||||
|
cookie,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (!reply) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
return (reply->type == XCB_ATOM_CARDINAL)
|
||||||
|
? std::make_optional(
|
||||||
|
*reinterpret_cast<ulong*>(xcb_get_property_value(reply)))
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<bool> XCBIsOverlapped(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect) {
|
||||||
|
const auto window = widget->window()->winId();
|
||||||
|
Expects(window != XCB_WINDOW_NONE);
|
||||||
|
|
||||||
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
|
if (!connection) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto root = base::Platform::XCB::GetRootWindowFromQt();
|
||||||
|
if (!root.has_value()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto windowWorkspace = XCBWindowWorkspace(
|
||||||
|
window);
|
||||||
|
|
||||||
|
const auto currentWorkspace = XCBCurrentWorkspace();
|
||||||
|
|
||||||
|
if (windowWorkspace.has_value()
|
||||||
|
&& currentWorkspace.has_value()
|
||||||
|
&& *windowWorkspace != *currentWorkspace
|
||||||
|
&& *windowWorkspace != 0xFFFFFFFF) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cookie = xcb_query_tree(connection, *root);
|
||||||
|
const auto reply = xcb_query_tree_reply(connection, cookie, nullptr);
|
||||||
|
if (!reply) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto guard = gsl::finally([&] { free(reply); });
|
||||||
|
|
||||||
|
const auto tree = xcb_query_tree_children(reply);
|
||||||
|
auto aboveTheWindow = false;
|
||||||
|
|
||||||
|
for (auto i = 0, l = xcb_query_tree_children_length(reply); i < l; ++i) {
|
||||||
|
if (window == tree[i]) {
|
||||||
|
aboveTheWindow = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aboveTheWindow) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto geometry = XCBWindowGeometry(tree[i]);
|
||||||
|
if (!rect.intersects(geometry)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto workspace = XCBWindowWorkspace(tree[i]);
|
||||||
|
if (workspace.has_value()
|
||||||
|
&& windowWorkspace.has_value()
|
||||||
|
&& *workspace != *windowWorkspace
|
||||||
|
&& *workspace != 0xFFFFFFFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mapped = XCBWindowMapped(tree[i]);
|
||||||
|
if (mapped.has_value() && !*mapped) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto hidden = XCBWindowHidden(tree[i]);
|
||||||
|
if (hidden.has_value()
|
||||||
|
&& *hidden) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool SetXCBFrameExtents(QWindow *window, const QMargins &extents) {
|
bool SetXCBFrameExtents(QWindow *window, const QMargins &extents) {
|
||||||
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
|
|
@ -169,10 +422,10 @@ bool TranslucentWindowsSupported(QPoint globalPosition) {
|
||||||
static auto WarnedAbout = base::flat_set<int>();
|
static auto WarnedAbout = base::flat_set<int>();
|
||||||
if (!WarnedAbout.contains(index)) {
|
if (!WarnedAbout.contains(index)) {
|
||||||
WarnedAbout.emplace(index);
|
WarnedAbout.emplace(index);
|
||||||
UI_LOG(("WARNING: Compositing is disabled for screen index %1 (for position %2,%3)").arg(index).arg(globalPosition.x()).arg(globalPosition.y()));
|
LOG(("WARNING: Compositing is disabled for screen index %1 (for position %2,%3)").arg(index).arg(globalPosition.x()).arg(globalPosition.y()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UI_LOG(("WARNING: Could not get screen for position %1,%2").arg(globalPosition.x()).arg(globalPosition.y()));
|
LOG(("WARNING: Could not get screen for position %1,%2").arg(globalPosition.x()).arg(globalPosition.y()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -189,12 +442,24 @@ void ClearTransientParent(not_null<QWidget*> widget) {
|
||||||
if (::Platform::IsX11()) {
|
if (::Platform::IsX11()) {
|
||||||
xcb_delete_property(
|
xcb_delete_property(
|
||||||
base::Platform::XCB::GetConnectionFromQt(),
|
base::Platform::XCB::GetConnectionFromQt(),
|
||||||
widget->windowHandle()->winId(),
|
widget->winId(),
|
||||||
XCB_ATOM_WM_TRANSIENT_FOR);
|
XCB_ATOM_WM_TRANSIENT_FOR);
|
||||||
}
|
}
|
||||||
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<bool> IsOverlapped(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect) {
|
||||||
|
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||||
|
if (::Platform::IsX11()) {
|
||||||
|
return XCBIsOverlapped(widget, rect);
|
||||||
|
}
|
||||||
|
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
bool WindowExtentsSupported() {
|
bool WindowExtentsSupported() {
|
||||||
#ifdef DESKTOP_APP_QT_PATCHED
|
#ifdef DESKTOP_APP_QT_PATCHED
|
||||||
if (::Platform::IsWayland()) {
|
if (::Platform::IsWayland()) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "ui/platform/mac/ui_utility_mac.h"
|
#include "ui/platform/mac/ui_utility_mac.h"
|
||||||
|
|
||||||
#include "ui/integration.h"
|
#include "ui/integration.h"
|
||||||
|
#include "base/qt_adapters.h"
|
||||||
|
|
||||||
#include <QtGui/QPainter>
|
#include <QtGui/QPainter>
|
||||||
#include <QtGui/QtEvents>
|
#include <QtGui/QtEvents>
|
||||||
|
|
@ -99,6 +100,60 @@ void DrainMainQueue() {
|
||||||
void IgnoreAllActivation(not_null<QWidget*> widget) {
|
void IgnoreAllActivation(not_null<QWidget*> widget) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<bool> IsOverlapped(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect) {
|
||||||
|
NSWindow *window = [reinterpret_cast<NSView*>(widget->window()->winId()) window];
|
||||||
|
Assert(window != nullptr);
|
||||||
|
|
||||||
|
if (![window isOnActiveSpace]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto nativeRect = CGRectMake(
|
||||||
|
rect.x(),
|
||||||
|
rect.y(),
|
||||||
|
rect.width(),
|
||||||
|
rect.height());
|
||||||
|
|
||||||
|
CGWindowID windowId = (CGWindowID)[window windowNumber];
|
||||||
|
const CGWindowListOption options = kCGWindowListExcludeDesktopElements
|
||||||
|
| kCGWindowListOptionOnScreenAboveWindow;
|
||||||
|
CFArrayRef windows = CGWindowListCopyWindowInfo(options, windowId);
|
||||||
|
if (!windows) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto guard = gsl::finally([&] {
|
||||||
|
CFRelease(windows);
|
||||||
|
});
|
||||||
|
NSMutableArray *list = (__bridge NSMutableArray*)windows;
|
||||||
|
for (NSDictionary *window in list) {
|
||||||
|
NSNumber *alphaValue = [window objectForKey:@"kCGWindowAlpha"];
|
||||||
|
const auto alpha = alphaValue ? [alphaValue doubleValue] : 1.;
|
||||||
|
if (alpha == 0.) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
NSString *owner = [window objectForKey:@"kCGWindowOwnerName"];
|
||||||
|
NSNumber *layerValue = [window objectForKey:@"kCGWindowLayer"];
|
||||||
|
const auto layer = layerValue ? [layerValue intValue] : 0;
|
||||||
|
if (owner && [owner isEqualToString:@"Dock"] && layer == 20) {
|
||||||
|
// It is always full screen.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CFDictionaryRef bounds = (__bridge CFDictionaryRef)[window objectForKey:@"kCGWindowBounds"];
|
||||||
|
if (!bounds) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CGRect rect;
|
||||||
|
if (!CGRectMakeWithDictionaryRepresentation(bounds, &rect)) {
|
||||||
|
continue;
|
||||||
|
} else if (CGRectIntersectsRect(rect, nativeRect)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
TitleControls::Layout TitleControlsLayout() {
|
TitleControls::Layout TitleControlsLayout() {
|
||||||
return TitleControls::Layout{
|
return TitleControls::Layout{
|
||||||
.left = {
|
.left = {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ void BringToBack(not_null<QWidget*> widget);
|
||||||
void IgnoreAllActivation(not_null<QWidget*> widget);
|
void IgnoreAllActivation(not_null<QWidget*> widget);
|
||||||
void ClearTransientParent(not_null<QWidget*> widget);
|
void ClearTransientParent(not_null<QWidget*> widget);
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<bool> IsOverlapped(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect);
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool UseMainQueueGeneric();
|
[[nodiscard]] constexpr bool UseMainQueueGeneric();
|
||||||
void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.
|
void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,11 @@
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
|
#include <wrl/client.h>
|
||||||
|
#include <Shobjidl.h>
|
||||||
|
|
||||||
|
using namespace Microsoft::WRL;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
namespace Platform {
|
namespace Platform {
|
||||||
|
|
||||||
|
|
@ -45,6 +50,55 @@ void IgnoreAllActivation(not_null<QWidget*> widget) {
|
||||||
ShowWindow(handle, SW_SHOW);
|
ShowWindow(handle, SW_SHOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<bool> IsOverlapped(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect) {
|
||||||
|
const auto handle = reinterpret_cast<HWND>(widget->window()->winId());
|
||||||
|
Expects(handle != nullptr);
|
||||||
|
|
||||||
|
ComPtr<IVirtualDesktopManager> virtualDesktopManager;
|
||||||
|
HRESULT hr = CoCreateInstance(
|
||||||
|
CLSID_VirtualDesktopManager,
|
||||||
|
nullptr,
|
||||||
|
CLSCTX_ALL,
|
||||||
|
IID_PPV_ARGS(&virtualDesktopManager));
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
BOOL isCurrent;
|
||||||
|
hr = virtualDesktopManager->IsWindowOnCurrentVirtualDesktop(
|
||||||
|
handle,
|
||||||
|
&isCurrent);
|
||||||
|
if (SUCCEEDED(hr) && !isCurrent) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<HWND> visited;
|
||||||
|
const RECT nativeRect{
|
||||||
|
rect.left(),
|
||||||
|
rect.top(),
|
||||||
|
rect.right(),
|
||||||
|
rect.bottom(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto curHandle = handle;
|
||||||
|
curHandle != nullptr && !ranges::contains(visited, curHandle);
|
||||||
|
curHandle = GetWindow(curHandle, GW_HWNDPREV)) {
|
||||||
|
visited.push_back(curHandle);
|
||||||
|
if (curHandle == handle) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RECT testRect, intersection;
|
||||||
|
if (IsWindowVisible(curHandle)
|
||||||
|
&& GetWindowRect(curHandle, &testRect)
|
||||||
|
&& IntersectRect(&intersection, &nativeRect, &testRect)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool ShowWindowMenu(QWindow *window) {
|
bool ShowWindowMenu(QWindow *window) {
|
||||||
const auto pos = QCursor::pos();
|
const auto pos = QCursor::pos();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
#include "ui/platform/win/ui_window_title_win.h"
|
#include "ui/platform/win/ui_window_title_win.h"
|
||||||
#include "base/platform/base_platform_info.h"
|
#include "base/platform/base_platform_info.h"
|
||||||
#include "base/platform/win/base_windows_safe_library.h"
|
#include "base/platform/win/base_windows_safe_library.h"
|
||||||
#include "base/integration.h"
|
#include "base/debug_log.h"
|
||||||
#include "styles/palette.h"
|
#include "styles/palette.h"
|
||||||
|
|
||||||
#include <QtCore/QAbstractNativeEventFilter>
|
#include <QtCore/QAbstractNativeEventFilter>
|
||||||
|
|
@ -75,7 +75,7 @@ bool IsTaskbarAutoHidden(LPRECT rcMon = nullptr, PUINT pEdge = nullptr) {
|
||||||
*pEdge = pos.uEdge;
|
*pEdge = pos.uEdge;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
base::Integration::Instance().logMessage("Failed to get taskbar pos");
|
DEBUG_LOG(("Failed to get taskbar pos"));
|
||||||
if (pEdge) {
|
if (pEdge) {
|
||||||
*pEdge = ABE_BOTTOM;
|
*pEdge = ABE_BOTTOM;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
//
|
//
|
||||||
#include "ui/style/style_core_font.h"
|
#include "ui/style/style_core_font.h"
|
||||||
|
|
||||||
#include "ui/style/style_core_custom_font.h"
|
|
||||||
#include "ui/ui_log.h"
|
|
||||||
#include "base/algorithm.h"
|
#include "base/algorithm.h"
|
||||||
|
#include "base/debug_log.h"
|
||||||
|
#include "ui/style/style_core_custom_font.h"
|
||||||
#include "ui/integration.h"
|
#include "ui/integration.h"
|
||||||
|
|
||||||
#include <QtCore/QMap>
|
#include <QtCore/QMap>
|
||||||
|
|
@ -49,13 +49,13 @@ bool ValidateFont(const QString &familyName, int flags = 0) {
|
||||||
checkFont.setUnderline(flags & style::internal::FontUnderline);
|
checkFont.setUnderline(flags & style::internal::FontUnderline);
|
||||||
auto realFamily = QFontInfo(checkFont).family();
|
auto realFamily = QFontInfo(checkFont).family();
|
||||||
if (realFamily.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
if (realFamily.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
||||||
UI_LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName, realFamily));
|
LOG(("Font Error: could not resolve '%1' font, got '%2'.").arg(familyName, realFamily));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto metrics = QFontMetrics(checkFont);
|
auto metrics = QFontMetrics(checkFont);
|
||||||
if (!metrics.height()) {
|
if (!metrics.height()) {
|
||||||
UI_LOG(("Font Error: got a zero height in '%1'.").arg(familyName));
|
LOG(("Font Error: got a zero height in '%1'.").arg(familyName));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,13 +65,13 @@ bool ValidateFont(const QString &familyName, int flags = 0) {
|
||||||
bool LoadCustomFont(const QString &filePath, const QString &familyName, int flags = 0) {
|
bool LoadCustomFont(const QString &filePath, const QString &familyName, int flags = 0) {
|
||||||
auto regularId = QFontDatabase::addApplicationFont(filePath);
|
auto regularId = QFontDatabase::addApplicationFont(filePath);
|
||||||
if (regularId < 0) {
|
if (regularId < 0) {
|
||||||
UI_LOG(("Font Error: could not add '%1'.").arg(filePath));
|
LOG(("Font Error: could not add '%1'.").arg(filePath));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto found = [&] {
|
const auto found = [&] {
|
||||||
for (auto &family : QFontDatabase::applicationFontFamilies(regularId)) {
|
for (auto &family : QFontDatabase::applicationFontFamilies(regularId)) {
|
||||||
UI_LOG(("Font: from '%1' loaded '%2'").arg(filePath, family));
|
LOG(("Font: from '%1' loaded '%2'").arg(filePath, family));
|
||||||
if (!family.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
if (!family.trimmed().compare(familyName, Qt::CaseInsensitive)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -79,7 +79,7 @@ bool LoadCustomFont(const QString &filePath, const QString &familyName, int flag
|
||||||
return false;
|
return false;
|
||||||
}();
|
}();
|
||||||
if (!found) {
|
if (!found) {
|
||||||
UI_LOG(("Font Error: could not locate '%1' font in '%2'.").arg(familyName, filePath));
|
LOG(("Font Error: could not locate '%1' font in '%2'.").arg(familyName, filePath));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,11 +194,6 @@ void StartFonts() {
|
||||||
|
|
||||||
style_InitFontsResource();
|
style_InitFontsResource();
|
||||||
|
|
||||||
const auto integrationExists = Ui::Integration::Exists();
|
|
||||||
if (integrationExists) {
|
|
||||||
Ui::Integration::Instance().startFontsBegin();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef DESKTOP_APP_USE_PACKAGED_FONTS
|
#ifndef DESKTOP_APP_USE_PACKAGED_FONTS
|
||||||
if (!UseSystemFont) {
|
if (!UseSystemFont) {
|
||||||
bool areGood[FontTypesCount] = { false };
|
bool areGood[FontTypesCount] = { false };
|
||||||
|
|
@ -222,7 +217,7 @@ void StartFonts() {
|
||||||
if (!areGood[i]) {
|
if (!areGood[i]) {
|
||||||
if (ValidateFont(fallback, flags)) {
|
if (ValidateFont(fallback, flags)) {
|
||||||
Overrides[i] = fallback;
|
Overrides[i] = fallback;
|
||||||
UI_LOG(("Fonts Info: Using '%1' instead of '%2'.").arg(fallback).arg(name));
|
LOG(("Fonts Info: Using '%1' instead of '%2'.").arg(fallback).arg(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Disable default fallbacks to Segoe UI, see:
|
// Disable default fallbacks to Segoe UI, see:
|
||||||
|
|
@ -264,10 +259,6 @@ void StartFonts() {
|
||||||
auto appFont = QApplication::font();
|
auto appFont = QApplication::font();
|
||||||
appFont.setStyleStrategy(QFont::PreferQuality);
|
appFont.setStyleStrategy(QFont::PreferQuality);
|
||||||
QApplication::setFont(appFont);
|
QApplication::setFont(appFont);
|
||||||
|
|
||||||
if (integrationExists) {
|
|
||||||
Ui::Integration::Instance().startFontsEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GetPossibleEmptyOverride(int32 flags) {
|
QString GetPossibleEmptyOverride(int32 flags) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#include "ui/text/text_block.h"
|
#include "ui/text/text_block.h"
|
||||||
|
|
||||||
#include "styles/style_basic.h"
|
#include "styles/style_basic.h"
|
||||||
#include "base/integration.h"
|
#include "base/debug_log.h"
|
||||||
|
|
||||||
#include <private/qfontengine_p.h>
|
#include <private/qfontengine_p.h>
|
||||||
|
|
||||||
|
|
@ -161,8 +161,8 @@ void addNextCluster(
|
||||||
for (auto i = 0; i < pos; ++i) {
|
for (auto i = 0; i < pos; ++i) {
|
||||||
str.append(QString::number(logClusters[i]));
|
str.append(QString::number(logClusters[i]));
|
||||||
}
|
}
|
||||||
base::Integration::Instance().logAssertionViolation(QString("text: %1 (from: %2, length: %3) part: %4").arg(DebugCurrentParsingString).arg(DebugCurrentParsingFrom).arg(DebugCurrentParsingLength).arg(DebugCurrentParsingPart));
|
LOG(("text: %1 (from: %2, length: %3) part: %4").arg(DebugCurrentParsingString).arg(DebugCurrentParsingFrom).arg(DebugCurrentParsingLength).arg(DebugCurrentParsingPart));
|
||||||
base::Integration::Instance().logAssertionViolation(QString("pos: %1, end: %2, glyphPosition: %3, glyphCount: %4, lineLength: %5, num_glyphs: %6, logClusters[0..pos]: %7").arg(pos).arg(end).arg(glyphPosition).arg(glyphCount).arg(line.length).arg(current.num_glyphs).arg(str.join(",")));
|
LOG(("pos: %1, end: %2, glyphPosition: %3, glyphCount: %4, lineLength: %5, num_glyphs: %6, logClusters[0..pos]: %7").arg(pos).arg(end).arg(glyphPosition).arg(glyphCount).arg(line.length).arg(current.num_glyphs).arg(str.join(",")));
|
||||||
Unexpected("Values in addNextCluster()");
|
Unexpected("Values in addNextCluster()");
|
||||||
}
|
}
|
||||||
Q_ASSERT((pos == end && glyphPosition == current.num_glyphs)
|
Q_ASSERT((pos == end && glyphPosition == current.num_glyphs)
|
||||||
|
|
|
||||||
|
|
@ -301,15 +301,20 @@ QStringList PrepareSearchWords(const QString &query, const QRegularExpression *S
|
||||||
bool CutPart(TextWithEntities &sending, TextWithEntities &left, int limit);
|
bool CutPart(TextWithEntities &sending, TextWithEntities &left, int limit);
|
||||||
|
|
||||||
struct MentionNameFields {
|
struct MentionNameFields {
|
||||||
MentionNameFields(int32 userId = 0, uint64 accessHash = 0) : userId(userId), accessHash(accessHash) {
|
MentionNameFields(uint64 userId = 0, uint64 accessHash = 0)
|
||||||
|
: userId(userId), accessHash(accessHash) {
|
||||||
}
|
}
|
||||||
int32 userId = 0;
|
uint64 userId = 0;
|
||||||
uint64 accessHash = 0;
|
uint64 accessHash = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline MentionNameFields MentionNameDataToFields(const QString &data) {
|
inline MentionNameFields MentionNameDataToFields(const QString &data) {
|
||||||
auto components = data.split('.');
|
auto components = data.split('.');
|
||||||
if (!components.isEmpty()) {
|
if (!components.isEmpty()) {
|
||||||
return { components.at(0).toInt(), (components.size() > 1) ? components.at(1).toULongLong() : 0 };
|
return {
|
||||||
|
components.at(0).toULongLong(),
|
||||||
|
(components.size() > 1) ? components.at(1).toULongLong() : 0
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return MentionNameFields{};
|
return MentionNameFields{};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
// This file is part of Desktop App Toolkit,
|
|
||||||
// a set of libraries for developing nice desktop applications.
|
|
||||||
//
|
|
||||||
// For license and copyright information please follow this link:
|
|
||||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
|
||||||
//
|
|
||||||
#include "ui/ui_log.h"
|
|
||||||
|
|
||||||
#include "ui/integration.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
|
|
||||||
void WriteLogEntry(const QString &message) {
|
|
||||||
if (Integration::Exists()) {
|
|
||||||
Integration::Instance().writeLogEntry(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Ui
|
|
||||||
15
ui/ui_log.h
15
ui/ui_log.h
|
|
@ -1,15 +0,0 @@
|
||||||
// This file is part of Desktop App Toolkit,
|
|
||||||
// a set of libraries for developing nice desktop applications.
|
|
||||||
//
|
|
||||||
// For license and copyright information please follow this link:
|
|
||||||
// https://github.com/desktop-app/legal/blob/master/LEGAL
|
|
||||||
//
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
|
|
||||||
void WriteLogEntry(const QString &message);
|
|
||||||
|
|
||||||
} // namespace Ui
|
|
||||||
|
|
||||||
#define UI_LOG(message) (::Ui::WriteLogEntry(QString message))
|
|
||||||
|
|
@ -6,11 +6,13 @@
|
||||||
//
|
//
|
||||||
#include "ui/ui_utility.h"
|
#include "ui/ui_utility.h"
|
||||||
|
|
||||||
|
#include "ui/platform/ui_platform_utility.h"
|
||||||
#include "ui/style/style_core.h"
|
#include "ui/style/style_core.h"
|
||||||
|
|
||||||
#include <QtWidgets/QApplication>
|
#include <QtWidgets/QApplication>
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
#include <QtGui/QtEvents>
|
#include <QtGui/QtEvents>
|
||||||
|
#include <private/qhighdpiscaling_p.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
|
@ -179,6 +181,36 @@ QPixmap PixmapFromImage(QImage &&image) {
|
||||||
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
|
return QPixmap::fromImage(std::move(image), Qt::ColorOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsContentVisible(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect) {
|
||||||
|
Expects(widget->window()->windowHandle());
|
||||||
|
|
||||||
|
const auto activeOrNotOverlapped = [&] {
|
||||||
|
if (const auto active = widget->isActiveWindow()) {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto mappedRect = QHighDpi::toNativePixels(
|
||||||
|
rect.isNull()
|
||||||
|
? QRect(
|
||||||
|
widget->mapToGlobal(QPoint()),
|
||||||
|
widget->mapToGlobal(
|
||||||
|
QPoint(widget->width(), widget->height())))
|
||||||
|
: QRect(
|
||||||
|
widget->mapToGlobal(rect.topLeft()),
|
||||||
|
widget->mapToGlobal(rect.bottomRight())),
|
||||||
|
widget->window()->windowHandle());
|
||||||
|
|
||||||
|
const auto overlapped = Platform::IsOverlapped(widget, mappedRect);
|
||||||
|
return overlapped.has_value() && !*overlapped;
|
||||||
|
}();
|
||||||
|
|
||||||
|
return activeOrNotOverlapped
|
||||||
|
&& widget->isVisible()
|
||||||
|
&& !widget->window()->isMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
void DisableCustomScaling() {
|
void DisableCustomScaling() {
|
||||||
qunsetenv("QT_DEVICE_PIXEL_RATIO");
|
qunsetenv("QT_DEVICE_PIXEL_RATIO");
|
||||||
qunsetenv("QT_SCALE_FACTOR");
|
qunsetenv("QT_SCALE_FACTOR");
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,10 @@ QPointer<const Widget> MakeWeak(not_null<const Widget*> object) {
|
||||||
|
|
||||||
[[nodiscard]] QPixmap PixmapFromImage(QImage &&image);
|
[[nodiscard]] QPixmap PixmapFromImage(QImage &&image);
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsContentVisible(
|
||||||
|
not_null<QWidget*> widget,
|
||||||
|
const QRect &rect = QRect());
|
||||||
|
|
||||||
void DisableCustomScaling();
|
void DisableCustomScaling();
|
||||||
|
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,11 @@ void RoundButton::setWidthChangedCallback(Fn<void()> callback) {
|
||||||
_numbers->setWidthChangedCallback(std::move(callback));
|
_numbers->setWidthChangedCallback(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RoundButton::setBrushOverride(std::optional<QBrush> brush) {
|
||||||
|
_brushOverride = std::move(brush);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void RoundButton::finishNumbersAnimation() {
|
void RoundButton::finishNumbersAnimation() {
|
||||||
if (_numbers) {
|
if (_numbers) {
|
||||||
_numbers->finishAnimating();
|
_numbers->finishAnimating();
|
||||||
|
|
@ -367,8 +372,12 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
||||||
const auto radius = rounded.height() / 2;
|
const auto radius = rounded.height() / 2;
|
||||||
PainterHighQualityEnabler hq(p);
|
PainterHighQualityEnabler hq(p);
|
||||||
p.setPen(Qt::NoPen);
|
p.setPen(Qt::NoPen);
|
||||||
p.setBrush(rect.color());
|
p.setBrush(_brushOverride ? *_brushOverride : rect.color()->b);
|
||||||
p.drawRoundedRect(fill, radius, radius);
|
p.drawRoundedRect(fill, radius, radius);
|
||||||
|
} else if (_brushOverride) {
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(*_brushOverride);
|
||||||
|
p.drawRoundedRect(fill, st::buttonRadius, st::buttonRadius);
|
||||||
} else {
|
} else {
|
||||||
rect.paint(p, fill);
|
rect.paint(p, fill);
|
||||||
}
|
}
|
||||||
|
|
@ -377,7 +386,7 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
auto over = isOver();
|
auto over = isOver();
|
||||||
auto down = isDown();
|
auto down = isDown();
|
||||||
if (over || down) {
|
if (!_brushOverride && (over || down)) {
|
||||||
drawRect(_roundRectOver);
|
drawRect(_roundRectOver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,7 @@ public:
|
||||||
setNumbersText(QString::number(numbers), numbers);
|
setNumbersText(QString::number(numbers), numbers);
|
||||||
}
|
}
|
||||||
void setWidthChangedCallback(Fn<void()> callback);
|
void setWidthChangedCallback(Fn<void()> callback);
|
||||||
|
void setBrushOverride(std::optional<QBrush> brush);
|
||||||
void finishNumbersAnimation();
|
void finishNumbersAnimation();
|
||||||
|
|
||||||
int contentWidth() const;
|
int contentWidth() const;
|
||||||
|
|
@ -165,6 +166,7 @@ private:
|
||||||
int _fullWidthOverride = 0;
|
int _fullWidthOverride = 0;
|
||||||
|
|
||||||
const style::RoundButton &_st;
|
const style::RoundButton &_st;
|
||||||
|
std::optional<QBrush> _brushOverride;
|
||||||
RoundRect _roundRect;
|
RoundRect _roundRect;
|
||||||
RoundRect _roundRectOver;
|
RoundRect _roundRectOver;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue