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/rp_widget.cpp
|
||||
ui/rp_widget.h
|
||||
ui/ui_log.cpp
|
||||
ui/ui_log.h
|
||||
ui/ui_utility.cpp
|
||||
ui/ui_utility.h
|
||||
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@
|
|||
#include "base/bytes.h"
|
||||
#include "base/openssl_help.h"
|
||||
#include "base/parse_helper.h"
|
||||
#include "base/debug_log.h"
|
||||
#include "ui/style/style_core.h"
|
||||
#include "ui/painter.h"
|
||||
#include "ui/ui_utility.h"
|
||||
#include "ui/ui_log.h"
|
||||
#include "styles/style_basic.h"
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
|
@ -218,7 +218,7 @@ void SaveToFile(int id, const QImage &image, int size, int index) {
|
|||
if (!f.open(QIODevice::WriteOnly)) {
|
||||
if (!QDir::current().mkpath(internal::CacheFileFolder())
|
||||
|| !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(size
|
||||
).arg(index));
|
||||
|
|
@ -244,7 +244,7 @@ void SaveToFile(int id, const QImage &image, int size, int index) {
|
|||
|| !write(data)
|
||||
|| !write(openssl::Sha256(bytes::make_span(header), data))
|
||||
|| 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(size));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,12 +36,6 @@ void Integration::textActionsUpdated() {
|
|||
void Integration::activationFromTopPanel() {
|
||||
}
|
||||
|
||||
void Integration::startFontsBegin() {
|
||||
}
|
||||
|
||||
void Integration::startFontsEnd() {
|
||||
}
|
||||
|
||||
QString Integration::timeFormat() {
|
||||
return u"hh:mm"_q;
|
||||
}
|
||||
|
|
@ -79,10 +73,6 @@ const Emoji::One *Integration::defaultEmojiVariant(const Emoji::One *emoji) {
|
|||
return emoji;
|
||||
}
|
||||
|
||||
QWidget *Integration::modalWindowParent() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rpl::producer<> Integration::forcePopupMenuHideRequests() {
|
||||
return rpl::never<rpl::empty_value>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,15 +35,11 @@ public:
|
|||
virtual void registerLeaveSubscription(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;
|
||||
|
||||
virtual void textActionsUpdated();
|
||||
virtual void activationFromTopPanel();
|
||||
|
||||
virtual void startFontsBegin();
|
||||
virtual void startFontsEnd();
|
||||
|
||||
[[nodiscard]] virtual QString timeFormat();
|
||||
|
||||
[[nodiscard]] virtual std::shared_ptr<ClickHandler> createLinkHandler(
|
||||
|
|
@ -56,8 +52,6 @@ public:
|
|||
[[nodiscard]] virtual const Emoji::One *defaultEmojiVariant(
|
||||
const Emoji::One *emoji);
|
||||
|
||||
[[nodiscard]] virtual QWidget *modalWindowParent();
|
||||
|
||||
[[nodiscard]] virtual rpl::producer<> forcePopupMenuHideRequests();
|
||||
|
||||
[[nodiscard]] virtual QString phraseContextCopyText();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Ui {
|
|||
void GenericBox::prepare() {
|
||||
_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());
|
||||
setInnerWidget(std::move(wrap));
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ void GenericBox::addSkip(int height) {
|
|||
}
|
||||
|
||||
not_null<Ui::VerticalLayout*> GenericBox::verticalLayout() {
|
||||
return _content.data();
|
||||
return _content;
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -120,7 +120,8 @@ private:
|
|||
FnMut<void(not_null<GenericBox*>)> _init;
|
||||
Fn<void()> _focus;
|
||||
Fn<void()> _showFinished;
|
||||
object_ptr<Ui::VerticalLayout> _content;
|
||||
object_ptr<Ui::VerticalLayout> _owned;
|
||||
not_null<Ui::VerticalLayout*> _content;
|
||||
int _width = 0;
|
||||
|
||||
};
|
||||
|
|
@ -166,7 +167,8 @@ inline GenericBox::GenericBox(
|
|||
MakeIniter(
|
||||
std::forward<InitMethod>(init),
|
||||
std::forward<InitArgs>(args)...))
|
||||
, _content(this) {
|
||||
, _owned(this)
|
||||
, _content(_owned.data()) {
|
||||
}
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
//
|
||||
#include "ui/platform/linux/ui_utility_linux.h"
|
||||
|
||||
#include "ui/ui_log.h"
|
||||
#include "base/platform/base_platform_info.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 "base/const_string.h"
|
||||
#include "base/qt_adapters.h"
|
||||
|
|
@ -33,6 +33,259 @@ namespace {
|
|||
constexpr auto kXCBFrameExtentsAtomName = "_GTK_FRAME_EXTENTS"_cs;
|
||||
|
||||
#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) {
|
||||
const auto connection = base::Platform::XCB::GetConnectionFromQt();
|
||||
if (!connection) {
|
||||
|
|
@ -169,10 +422,10 @@ bool TranslucentWindowsSupported(QPoint globalPosition) {
|
|||
static auto WarnedAbout = base::flat_set<int>();
|
||||
if (!WarnedAbout.contains(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 {
|
||||
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()) {
|
||||
xcb_delete_property(
|
||||
base::Platform::XCB::GetConnectionFromQt(),
|
||||
widget->windowHandle()->winId(),
|
||||
widget->winId(),
|
||||
XCB_ATOM_WM_TRANSIENT_FOR);
|
||||
}
|
||||
#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() {
|
||||
#ifdef DESKTOP_APP_QT_PATCHED
|
||||
if (::Platform::IsWayland()) {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "ui/platform/mac/ui_utility_mac.h"
|
||||
|
||||
#include "ui/integration.h"
|
||||
#include "base/qt_adapters.h"
|
||||
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QtEvents>
|
||||
|
|
@ -99,6 +100,60 @@ void DrainMainQueue() {
|
|||
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() {
|
||||
return TitleControls::Layout{
|
||||
.left = {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@ void BringToBack(not_null<QWidget*> widget);
|
|||
void IgnoreAllActivation(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();
|
||||
void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,11 @@
|
|||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QWindow>
|
||||
|
||||
#include <wrl/client.h>
|
||||
#include <Shobjidl.h>
|
||||
|
||||
using namespace Microsoft::WRL;
|
||||
|
||||
namespace Ui {
|
||||
namespace Platform {
|
||||
|
||||
|
|
@ -45,6 +50,55 @@ void IgnoreAllActivation(not_null<QWidget*> widget) {
|
|||
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) {
|
||||
const auto pos = QCursor::pos();
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#include "ui/platform/win/ui_window_title_win.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/win/base_windows_safe_library.h"
|
||||
#include "base/integration.h"
|
||||
#include "base/debug_log.h"
|
||||
#include "styles/palette.h"
|
||||
|
||||
#include <QtCore/QAbstractNativeEventFilter>
|
||||
|
|
@ -75,7 +75,7 @@ bool IsTaskbarAutoHidden(LPRECT rcMon = nullptr, PUINT pEdge = nullptr) {
|
|||
*pEdge = pos.uEdge;
|
||||
}
|
||||
} else {
|
||||
base::Integration::Instance().logMessage("Failed to get taskbar pos");
|
||||
DEBUG_LOG(("Failed to get taskbar pos"));
|
||||
if (pEdge) {
|
||||
*pEdge = ABE_BOTTOM;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,9 +6,9 @@
|
|||
//
|
||||
#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/debug_log.h"
|
||||
#include "ui/style/style_core_custom_font.h"
|
||||
#include "ui/integration.h"
|
||||
|
||||
#include <QtCore/QMap>
|
||||
|
|
@ -49,13 +49,13 @@ bool ValidateFont(const QString &familyName, int flags = 0) {
|
|||
checkFont.setUnderline(flags & style::internal::FontUnderline);
|
||||
auto realFamily = QFontInfo(checkFont).family();
|
||||
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;
|
||||
}
|
||||
|
||||
auto metrics = QFontMetrics(checkFont);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -65,13 +65,13 @@ bool ValidateFont(const QString &familyName, int flags = 0) {
|
|||
bool LoadCustomFont(const QString &filePath, const QString &familyName, int flags = 0) {
|
||||
auto regularId = QFontDatabase::addApplicationFont(filePath);
|
||||
if (regularId < 0) {
|
||||
UI_LOG(("Font Error: could not add '%1'.").arg(filePath));
|
||||
LOG(("Font Error: could not add '%1'.").arg(filePath));
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto found = [&] {
|
||||
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)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -79,7 +79,7 @@ bool LoadCustomFont(const QString &filePath, const QString &familyName, int flag
|
|||
return false;
|
||||
}();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -194,11 +194,6 @@ void StartFonts() {
|
|||
|
||||
style_InitFontsResource();
|
||||
|
||||
const auto integrationExists = Ui::Integration::Exists();
|
||||
if (integrationExists) {
|
||||
Ui::Integration::Instance().startFontsBegin();
|
||||
}
|
||||
|
||||
#ifndef DESKTOP_APP_USE_PACKAGED_FONTS
|
||||
if (!UseSystemFont) {
|
||||
bool areGood[FontTypesCount] = { false };
|
||||
|
|
@ -222,7 +217,7 @@ void StartFonts() {
|
|||
if (!areGood[i]) {
|
||||
if (ValidateFont(fallback, flags)) {
|
||||
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:
|
||||
|
|
@ -264,10 +259,6 @@ void StartFonts() {
|
|||
auto appFont = QApplication::font();
|
||||
appFont.setStyleStrategy(QFont::PreferQuality);
|
||||
QApplication::setFont(appFont);
|
||||
|
||||
if (integrationExists) {
|
||||
Ui::Integration::Instance().startFontsEnd();
|
||||
}
|
||||
}
|
||||
|
||||
QString GetPossibleEmptyOverride(int32 flags) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
#include "ui/text/text_block.h"
|
||||
|
||||
#include "styles/style_basic.h"
|
||||
#include "base/integration.h"
|
||||
#include "base/debug_log.h"
|
||||
|
||||
#include <private/qfontengine_p.h>
|
||||
|
||||
|
|
@ -161,8 +161,8 @@ void addNextCluster(
|
|||
for (auto i = 0; i < pos; ++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));
|
||||
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(("text: %1 (from: %2, length: %3) part: %4").arg(DebugCurrentParsingString).arg(DebugCurrentParsingFrom).arg(DebugCurrentParsingLength).arg(DebugCurrentParsingPart));
|
||||
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()");
|
||||
}
|
||||
Q_ASSERT((pos == end && glyphPosition == current.num_glyphs)
|
||||
|
|
|
|||
|
|
@ -301,17 +301,22 @@ QStringList PrepareSearchWords(const QString &query, const QRegularExpression *S
|
|||
bool CutPart(TextWithEntities &sending, TextWithEntities &left, int limit);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
inline MentionNameFields MentionNameDataToFields(const QString &data) {
|
||||
auto components = data.split('.');
|
||||
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{};
|
||||
}
|
||||
|
||||
inline QString MentionNameDataFromFields(const MentionNameFields &fields) {
|
||||
|
|
|
|||
|
|
@ -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/platform/ui_platform_utility.h"
|
||||
#include "ui/style/style_core.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QtEvents>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
|
|
@ -179,6 +181,36 @@ QPixmap PixmapFromImage(QImage &&image) {
|
|||
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() {
|
||||
qunsetenv("QT_DEVICE_PIXEL_RATIO");
|
||||
qunsetenv("QT_SCALE_FACTOR");
|
||||
|
|
|
|||
|
|
@ -187,6 +187,10 @@ QPointer<const Widget> MakeWeak(not_null<const Widget*> object) {
|
|||
|
||||
[[nodiscard]] QPixmap PixmapFromImage(QImage &&image);
|
||||
|
||||
[[nodiscard]] bool IsContentVisible(
|
||||
not_null<QWidget*> widget,
|
||||
const QRect &rect = QRect());
|
||||
|
||||
void DisableCustomScaling();
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -296,6 +296,11 @@ void RoundButton::setWidthChangedCallback(Fn<void()> callback) {
|
|||
_numbers->setWidthChangedCallback(std::move(callback));
|
||||
}
|
||||
|
||||
void RoundButton::setBrushOverride(std::optional<QBrush> brush) {
|
||||
_brushOverride = std::move(brush);
|
||||
update();
|
||||
}
|
||||
|
||||
void RoundButton::finishNumbersAnimation() {
|
||||
if (_numbers) {
|
||||
_numbers->finishAnimating();
|
||||
|
|
@ -367,8 +372,12 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||
const auto radius = rounded.height() / 2;
|
||||
PainterHighQualityEnabler hq(p);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(rect.color());
|
||||
p.setBrush(_brushOverride ? *_brushOverride : rect.color()->b);
|
||||
p.drawRoundedRect(fill, radius, radius);
|
||||
} else if (_brushOverride) {
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(*_brushOverride);
|
||||
p.drawRoundedRect(fill, st::buttonRadius, st::buttonRadius);
|
||||
} else {
|
||||
rect.paint(p, fill);
|
||||
}
|
||||
|
|
@ -377,7 +386,7 @@ void RoundButton::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto over = isOver();
|
||||
auto down = isDown();
|
||||
if (over || down) {
|
||||
if (!_brushOverride && (over || down)) {
|
||||
drawRect(_roundRectOver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,7 @@ public:
|
|||
setNumbersText(QString::number(numbers), numbers);
|
||||
}
|
||||
void setWidthChangedCallback(Fn<void()> callback);
|
||||
void setBrushOverride(std::optional<QBrush> brush);
|
||||
void finishNumbersAnimation();
|
||||
|
||||
int contentWidth() const;
|
||||
|
|
@ -165,6 +166,7 @@ private:
|
|||
int _fullWidthOverride = 0;
|
||||
|
||||
const style::RoundButton &_st;
|
||||
std::optional<QBrush> _brushOverride;
|
||||
RoundRect _roundRect;
|
||||
RoundRect _roundRectOver;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue