Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Eric Kotato 2020-01-18 17:55:26 +03:00
commit 1d2bfb4863
30 changed files with 455 additions and 57 deletions

201
CMakeLists.txt Normal file
View file

@ -0,0 +1,201 @@
# 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
add_library(lib_ui OBJECT)
add_library(desktop-app::lib_ui ALIAS lib_ui)
init_target(lib_ui)
include(cmake/generate_palette.cmake)
include(cmake/generate_styles.cmake)
include(cmake/generate_emoji.cmake)
get_filename_component(src_loc . REALPATH)
set(style_files
ui/basic.style
ui/layers/layers.style
ui/widgets/widgets.style
)
generate_palette(lib_ui ui/colors.palette)
generate_styles(lib_ui ${src_loc} "${style_files}" ui/colors.palette)
generate_emoji(lib_ui emoji_suggestions/emoji_autocomplete.json)
set_target_properties(lib_ui PROPERTIES AUTOMOC ON AUTORCC ON)
target_precompile_headers(lib_ui PRIVATE ${src_loc}/ui/ui_pch.h)
nice_target_sources(lib_ui ${src_loc}
PRIVATE
${style_files}
ui/colors.palette
emoji_suggestions/emoji_autocomplete.json
fonts/fonts.qrc
qt_conf/mac.qrc
qt_conf/win.qrc
ui/effects/animation_value.cpp
ui/effects/animation_value.h
ui/effects/animations.cpp
ui/effects/animations.h
ui/effects/cross_animation.cpp
ui/effects/cross_animation.h
ui/effects/fade_animation.cpp
ui/effects/fade_animation.h
ui/effects/numbers_animation.cpp
ui/effects/numbers_animation.h
ui/effects/panel_animation.cpp
ui/effects/panel_animation.h
ui/effects/radial_animation.cpp
ui/effects/radial_animation.h
ui/effects/ripple_animation.cpp
ui/effects/ripple_animation.h
ui/effects/slide_animation.cpp
ui/effects/slide_animation.h
ui/image/image_prepare.cpp
ui/image/image_prepare.h
ui/layers/box_content.cpp
ui/layers/box_content.h
ui/layers/box_layer_widget.cpp
ui/layers/box_layer_widget.h
ui/layers/generic_box.cpp
ui/layers/generic_box.h
ui/layers/layer_manager.cpp
ui/layers/layer_manager.h
ui/layers/layer_widget.cpp
ui/layers/layer_widget.h
ui/platform/linux/ui_window_linux.cpp
ui/platform/linux/ui_window_linux.h
ui/platform/linux/ui_utility_linux.cpp
ui/platform/linux/ui_utility_linux.h
ui/platform/mac/ui_window_mac.h
ui/platform/mac/ui_window_mac.mm
ui/platform/mac/ui_window_title_mac.h
ui/platform/mac/ui_window_title_mac.mm
ui/platform/mac/ui_utility_mac.h
ui/platform/mac/ui_utility_mac.mm
ui/platform/win/ui_window_shadow_win.cpp
ui/platform/win/ui_window_shadow_win.h
ui/platform/win/ui_window_title_win.cpp
ui/platform/win/ui_window_title_win.h
ui/platform/win/ui_window_win.cpp
ui/platform/win/ui_window_win.h
ui/platform/win/ui_utility_win.cpp
ui/platform/win/ui_utility_win.h
ui/platform/ui_platform_window.h
ui/platform/ui_platform_utility.h
ui/style/style_core.cpp
ui/style/style_core.h
ui/style/style_core_color.cpp
ui/style/style_core_color.h
ui/style/style_core_direction.cpp
ui/style/style_core_direction.h
ui/style/style_core_font.cpp
ui/style/style_core_font.h
ui/style/style_core_icon.cpp
ui/style/style_core_icon.h
ui/style/style_core_scale.cpp
ui/style/style_core_scale.h
ui/style/style_core_types.cpp
ui/style/style_core_types.h
ui/text/text.cpp
ui/text/text.h
ui/text/text_block.cpp
ui/text/text_block.h
ui/text/text_entity.cpp
ui/text/text_entity.h
ui/text/text_isolated_emoji.h
ui/text/text_utilities.cpp
ui/text/text_utilities.h
ui/toast/toast.cpp
ui/toast/toast.h
ui/toast/toast_manager.cpp
ui/toast/toast_manager.h
ui/toast/toast_widget.cpp
ui/toast/toast_widget.h
ui/widgets/box_content_divider.cpp
ui/widgets/box_content_divider.h
ui/widgets/buttons.cpp
ui/widgets/buttons.h
ui/widgets/checkbox.cpp
ui/widgets/checkbox.h
ui/widgets/dropdown_menu.cpp
ui/widgets/dropdown_menu.h
ui/widgets/inner_dropdown.cpp
ui/widgets/inner_dropdown.h
ui/widgets/input_fields.cpp
ui/widgets/input_fields.h
ui/widgets/labels.cpp
ui/widgets/labels.h
ui/widgets/menu.cpp
ui/widgets/menu.h
ui/widgets/popup_menu.cpp
ui/widgets/popup_menu.h
ui/widgets/scroll_area.cpp
ui/widgets/scroll_area.h
ui/widgets/shadow.cpp
ui/widgets/shadow.h
ui/widgets/tooltip.cpp
ui/widgets/tooltip.h
ui/widgets/window.cpp
ui/widgets/window.h
ui/wrap/fade_wrap.cpp
ui/wrap/fade_wrap.h
ui/wrap/padding_wrap.cpp
ui/wrap/padding_wrap.h
ui/wrap/slide_wrap.cpp
ui/wrap/slide_wrap.h
ui/wrap/vertical_layout.cpp
ui/wrap/vertical_layout.h
ui/wrap/wrap.h
ui/abstract_button.cpp
ui/abstract_button.h
ui/basic_click_handlers.cpp
ui/basic_click_handlers.h
ui/click_handler.cpp
ui/click_handler.h
ui/delayed_activation.cpp
ui/delayed_activation.h
ui/emoji_config.cpp
ui/emoji_config.h
ui/focus_persister.h
ui/inactive_press.cpp
ui/inactive_press.h
ui/integration.cpp
ui/integration.h
ui/main_queue_processor.cpp
ui/main_queue_processor.h
ui/painter.h
ui/ph.cpp
ui/ph.h
ui/rect_part.h
ui/round_rect.cpp
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
emoji_suggestions/emoji_suggestions.cpp
emoji_suggestions/emoji_suggestions.h
emoji_suggestions/emoji_suggestions_helper.h
)
if (NOT DESKTOP_APP_USE_PACKAGED)
nice_target_sources(lib_ui ${src_loc} PRIVATE qt_conf/linux.qrc)
endif()
target_include_directories(lib_ui
PUBLIC
${src_loc}
${src_loc}/emoji_suggestions
)
target_link_libraries(lib_ui
PUBLIC
desktop-app::lib_base
)

View file

@ -0,0 +1,29 @@
function(generate_emoji target_name suggestions_json)
set(gen_dst ${CMAKE_CURRENT_BINARY_DIR}/gen)
file(MAKE_DIRECTORY ${gen_dst})
set(gen_timestamp ${gen_dst}/emoji.timestamp)
set(gen_files
${gen_dst}/emoji.cpp
${gen_dst}/emoji.h
${gen_dst}/emoji_suggestions_data.cpp
${gen_dst}/emoji_suggestions_data.h
)
set(gen_src ${CMAKE_CURRENT_SOURCE_DIR}/${suggestions_json})
add_custom_command(
OUTPUT
${gen_timestamp}
BYPRODUCTS
${gen_files}
COMMAND
codegen_emoji
-o${gen_dst}
${gen_src}
COMMENT "Generating emoji (${target_name})"
DEPENDS
codegen_emoji
${gen_src}
)
generate_target(${target_name} emoji ${gen_timestamp} "${gen_files}" ${gen_dst})
endfunction()

View file

@ -0,0 +1,32 @@
function(generate_palette target_name palette_file)
set(gen_dst ${CMAKE_CURRENT_BINARY_DIR}/gen)
file(MAKE_DIRECTORY ${gen_dst})
set(gen_timestamp ${gen_dst}/styles/palette.timestamp)
set(gen_files
${gen_dst}/styles/palette.cpp
${gen_dst}/styles/palette.h
)
set(gen_src ${CMAKE_CURRENT_SOURCE_DIR}/${palette_file})
add_custom_command(
OUTPUT
${gen_timestamp}
BYPRODUCTS
${gen_files}
COMMAND
codegen_style
-I${gen_dst}
-o${gen_dst}/styles
-t${gen_dst}/styles/palette
-w${CMAKE_CURRENT_SOURCE_DIR}
${gen_src}
COMMENT "Generating palette (${target_name})"
DEPENDS
codegen_style
${gen_src}
MAIN_DEPENDENCY
${gen_src}
)
generate_target(${target_name} palette ${gen_timestamp} "${gen_files}" ${gen_dst})
endfunction()

View file

@ -0,0 +1,40 @@
function(generate_styles target_name src_loc style_files dependent_style_files)
set(gen_dst ${CMAKE_CURRENT_BINARY_DIR}/gen)
file(MAKE_DIRECTORY ${gen_dst})
set(gen_timestamp ${gen_dst}/styles/${target_name}_style.timestamp)
set(gen_files "")
set(full_generation_sources "")
set(full_dependencies_list ${dependent_style_files})
foreach (file ${style_files})
list(APPEND full_generation_sources ${src_loc}/${file})
get_filename_component(file_name ${file} NAME_WLE)
list(APPEND gen_files
${gen_dst}/styles/style_${file_name}.cpp
${gen_dst}/styles/style_${file_name}.h
)
endforeach()
list(APPEND full_dependencies_list ${full_generation_sources})
add_custom_command(
OUTPUT
${gen_timestamp}
BYPRODUCTS
${gen_files}
COMMAND
codegen_style
-I${src_loc}
-I${submodules_loc}/lib_ui
-I${submodules_loc}/Resources
-o${gen_dst}/styles
-t${gen_dst}/styles/${target_name}_style
-w${CMAKE_CURRENT_SOURCE_DIR}
${full_generation_sources}
COMMENT "Generating styles (${target_name})"
DEPENDS
codegen_style
${full_dependencies_list}
)
generate_target(${target_name} styles ${gen_timestamp} "${gen_files}" ${gen_dst})
endfunction()

View file

@ -16,12 +16,17 @@
#include <QtGui/QDesktopServices>
#include <QtGui/QGuiApplication>
QString TextClickHandler::readable() const {
const auto result = url();
return result.startsWith(qstr("internal:")) ? QString() : result;
}
UrlClickHandler::UrlClickHandler(const QString &url, bool fullDisplayed)
: TextClickHandler(fullDisplayed)
, _originalUrl(url) {
if (isEmail()) {
_readable = _originalUrl;
} else {
} else if (!_originalUrl.startsWith(qstr("internal:"))) {
const auto original = QUrl(_originalUrl);
const auto good = QUrl(original.isValid()
? original.toEncoded()

View file

@ -29,9 +29,7 @@ public:
protected:
virtual QString url() const = 0;
virtual QString readable() const {
return url();
}
virtual QString readable() const;
bool _fullDisplayed;

View file

@ -558,7 +558,7 @@ outdateSoonBg: #e08543; // operating system version is soon outdated bar backgro
outdatedBg: #e05745; // operating system version is already outdated bar background
// spellcheck
spellUnderline: #ff000088; // misspelled words
spellUnderline: #ff000088 | attentionButtonFg; // misspelled words
walletTitleBg: #121213; // wallet window title background when window is inactive
walletTitleBgActive: walletTitleBg; // wallet window title background when window is active

View file

@ -113,6 +113,7 @@ void Manager::stop(not_null<Basic*> animation) {
const auto i = ranges::find(_active, value, proj);
if (i != end(_active)) {
*i = nullptr;
_removedWhileUpdating = true;
}
} else if (empty(_active)) {
stopTimer();
@ -138,6 +139,12 @@ void Manager::update() {
};
_active.erase(ranges::remove_if(_active, isFinished), end(_active));
if (_removedWhileUpdating) {
_removedWhileUpdating = false;
const auto proj = &ActiveBasicPointer::get;
_active.erase(ranges::remove(_active, nullptr, proj), end(_active));
}
if (!empty(_starting)) {
_active.insert(
end(_active),

View file

@ -198,6 +198,7 @@ private:
crl::time _lastUpdateTime = 0;
int _timerId = 0;
bool _updating = false;
bool _removedWhileUpdating = false;
bool _scheduled = false;
bool _forceImmediateUpdate = false;
std::vector<ActiveBasicPointer> _active;

View file

@ -144,7 +144,14 @@ void InfiniteRadialAnimation::draw(
QPainter &p,
QPoint position,
int outerWidth) {
draw(p, position, _st.size, outerWidth);
Draw(
p,
computeState(),
position,
_st.size,
outerWidth,
_st.color,
_st.thickness);
}
void InfiniteRadialAnimation::draw(
@ -152,8 +159,24 @@ void InfiniteRadialAnimation::draw(
QPoint position,
QSize size,
int outerWidth) {
const auto state = computeState();
Draw(
p,
computeState(),
position,
size,
outerWidth,
_st.color,
_st.thickness);
}
void InfiniteRadialAnimation::Draw(
QPainter &p,
const RadialState &state,
QPoint position,
QSize size,
int outerWidth,
QPen pen,
int thickness) {
auto o = p.opacity();
p.setOpacity(o * state.shown);
@ -166,10 +189,9 @@ void InfiniteRadialAnimation::draw(
const auto was = p.pen();
const auto brush = p.brush();
if (anim::Disabled()) {
anim::DrawStaticLoading(p, rect, _st.thickness, _st.color);
anim::DrawStaticLoading(p, rect, thickness, pen);
} else {
auto pen = _st.color->p;
pen.setWidth(_st.thickness);
pen.setWidth(thickness);
pen.setCapStyle(Qt::RoundCap);
p.setPen(pen);

View file

@ -27,10 +27,10 @@ public:
template <typename Callback>
RadialAnimation(Callback &&callback);
float64 opacity() const {
[[nodiscard]] float64 opacity() const {
return _opacity;
}
bool animating() const {
[[nodiscard]] bool animating() const {
return _animation.animating();
}
@ -44,7 +44,7 @@ public:
int32 thickness,
style::color color) const;
RadialState computeState() const;
[[nodiscard]] RadialState computeState() const;
private:
crl::time _firstStart = 0;
@ -72,7 +72,7 @@ public:
Callback &&callback,
const style::InfiniteRadialAnimation &st);
bool animating() const {
[[nodiscard]] bool animating() const {
return _animation.animating();
}
@ -89,7 +89,16 @@ public:
QSize size,
int outerWidth);
RadialState computeState();
static void Draw(
QPainter &p,
const RadialState &state,
QPoint position,
QSize size,
int outerWidth,
QPen pen,
int thickness);
[[nodiscard]] RadialState computeState();
private:
const style::InfiniteRadialAnimation &_st;

View file

@ -516,7 +516,6 @@ void prepareRound(
}
Assert(!image.isNull());
image.setDevicePixelRatio(style::DevicePixelRatio());
image = std::move(image).convertToFormat(
QImage::Format_ARGB32_Premultiplied);
Assert(!image.isNull());

View file

@ -184,6 +184,14 @@ public:
return _delegate;
}
void setNoContentMargin(bool noContentMargin) {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin);
}
getDelegate()->setNoContentMargin(noContentMargin);
}
public slots:
void onScrollToY(int top, int bottom = -1);
@ -196,13 +204,6 @@ protected:
getDelegate()->setLayerType(layerType);
}
void setNoContentMargin(bool noContentMargin) {
if (_noContentMargin != noContentMargin) {
_noContentMargin = noContentMargin;
setAttribute(Qt::WA_OpaquePaintEvent, !_noContentMargin);
}
getDelegate()->setNoContentMargin(noContentMargin);
}
void setDimensions(
int newWidth,
int maxHeight,

View file

@ -462,10 +462,10 @@ void LayerStackWidget::setCacheImages() {
void LayerStackWidget::closeLayer(not_null<LayerWidget*> layer) {
const auto weak = Ui::MakeWeak(layer.get());
if (weak->inFocusChain()) {
if (Ui::InFocusChain(layer)) {
setFocus();
}
if (!weak || !weak->setClosing()) {
if (!layer->setClosing()) {
// This layer is already closing.
return;
} else if (!weak) {
@ -734,9 +734,11 @@ void LayerStackWidget::appendBox(
LayerWidget *LayerStackWidget::pushBox(
object_ptr<BoxContent> box,
anim::type animated) {
auto oldLayer = currentLayer();
const auto oldLayer = currentLayer();
if (oldLayer) {
if (oldLayer->inFocusChain()) setFocus();
if (Ui::InFocusChain(oldLayer)) {
setFocus();
}
oldLayer->hide();
}
_layers.push_back(
@ -793,7 +795,7 @@ void LayerStackWidget::clearClosingLayers() {
while (!_closingLayers.empty()) {
const auto index = _closingLayers.size() - 1;
const auto layer = _closingLayers.back().get();
if (layer->inFocusChain()) {
if (Ui::InFocusChain(layer)) {
setFocus();
}

View file

@ -43,5 +43,8 @@ bool TranslucentWindowsSupported(QPoint globalPosition) {
return false;
}
void IgnoreAllActivation(not_null<QWidget*> widget) {
}
} // namespace Platform
} // namespace Ui

View file

@ -91,5 +91,8 @@ void DrainMainQueue() {
_dispatch_main_queue_callback_4CF(nullptr);
}
void IgnoreAllActivation(not_null<QWidget*> widget) {
}
} // namespace Platform
} // namespace Ui

View file

@ -25,6 +25,7 @@ void ReInitOnTopPanel(not_null<QWidget*> panel);
void UpdateOverlayed(not_null<QWidget*> widget);
void ShowOverAll(not_null<QWidget*> widget, bool canFocus = true);
void BringToBack(not_null<QWidget*> widget);
void IgnoreAllActivation(not_null<QWidget*> widget);
[[nodiscard]] constexpr bool UseMainQueueGeneric();
void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.

View file

@ -8,6 +8,8 @@
#include <QtWidgets/QApplication>
#include "base/platform/win/base_windows_h.h"
namespace Ui {
namespace Platform {
@ -27,5 +29,18 @@ void UpdateOverlayed(not_null<QWidget*> widget) {
if (!wv) widget->setAttribute(Qt::WA_WState_Visible, false);
}
void IgnoreAllActivation(not_null<QWidget*> widget) {
const auto handle = reinterpret_cast<HWND>(widget->winId());
Assert(handle != nullptr);
ShowWindow(handle, SW_HIDE);
const auto style = GetWindowLong(handle, GWL_EXSTYLE);
SetWindowLong(
handle,
GWL_EXSTYLE,
style | WS_EX_NOACTIVATE | WS_EX_APPWINDOW);
ShowWindow(handle, SW_SHOW);
}
} // namespace Platform
} // namespace Ui

View file

@ -53,7 +53,8 @@ void TitleWidget::setResizeEnabled(bool enabled) {
void TitleWidget::init() {
_minimize->setClickedCallback([=] {
window()->setWindowState(Qt::WindowMinimized);
window()->setWindowState(
window()->windowState() | Qt::WindowMinimized);
_minimize->clearState();
});
_minimize->setPointerCursor(false);

View file

@ -338,9 +338,12 @@ bool WindowHelper::handleNativeEvent(
}
const auto command = LOWORD(wParam);
switch (command) {
case SC_CLOSE: _window->close(); return true;
case SC_CLOSE:
_window->close();
return true;
case SC_MINIMIZE:
_window->setWindowState(Qt::WindowMinimized);
_window->setWindowState(
_window->windowState() | Qt::WindowMinimized);
return true;
case SC_MAXIMIZE:
if (!fixedSize()) {

View file

@ -28,10 +28,6 @@ public:
return QMargins();
}
bool inFocusChain() const {
return Ui::InFocusChain(this);
}
void hideChildren() {
for (auto child : Base::children()) {
if (child->isWidgetType()) {

View file

@ -20,9 +20,9 @@ void style_InitFontsResource() {
Q_INIT_RESOURCE(win);
#elif defined Q_OS_MAC // Q_OS_WIN
Q_INIT_RESOURCE(mac);
#else // Q_OS_WIN || Q_OS_MAC
#elif defined Q_OS_LINUX && !defined DESKTOP_APP_USE_PACKAGED // Q_OS_WIN || Q_OS_MAC
Q_INIT_RESOURCE(linux);
#endif // Q_OS_WIN || Q_OS_MAC || Q_OS_LINUX
#endif // Q_OS_WIN || Q_OS_MAC || (Q_OS_LINUX && !DESKTOP_APP_USE_PACKAGED)
}
namespace style {

View file

@ -117,19 +117,19 @@ bool ComputeCheckTilde(const style::TextStyle &st) {
bool chIsBad(QChar ch) {
return (ch == 0)
|| (ch >= 8232 && ch < 8237)
|| (ch >= 65024 && ch < 65040 && ch != 65039)
|| (ch >= 127 && ch < 160 && ch != 156)
|| (ch >= 8232 && ch < 8237)
|| (ch >= 65024 && ch < 65040 && ch != 65039)
|| (ch >= 127 && ch < 160 && ch != 156)
// qt harfbuzz crash see https://github.com/telegramdesktop/tdesktop/issues/4551
|| (Platform::IsMac() && ch == 6158)
// qt harfbuzz crash see https://github.com/telegramdesktop/tdesktop/issues/4551
|| (Platform::IsMac() && ch == 6158)
// tmp hack see https://bugreports.qt.io/browse/QTBUG-48910
// tmp hack see https://bugreports.qt.io/browse/QTBUG-48910
|| (Platform::IsMac10_11OrGreater()
&& !Platform::IsMac10_12OrGreater()
&& ch >= 0x0B00
&& ch <= 0x0B7F
&& chIsDiac(ch));
&& ch <= 0x0B7F
&& chIsDiac(ch));
}
QString textcmdSkipBlock(ushort w, ushort h) {
@ -1518,7 +1518,7 @@ private:
eShapeLine(line);
int firstItem = engine.findItem(line.from), lastItem = engine.findItem(line.from + line.length - 1);
int nItems = (firstItem >= 0 && lastItem >= firstItem) ? (lastItem - firstItem + 1) : 0;
int nItems = (firstItem >= 0 && lastItem >= firstItem) ? (lastItem - firstItem + 1) : 0;
if (!nItems) {
return true;
}
@ -1545,7 +1545,7 @@ private:
}
}
}
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
if (style::RightToLeft() && skipIndex == nItems - 1) {
for (int32 i = nItems; i > 1;) {
--i;
@ -1870,7 +1870,7 @@ private:
_wLeft = _w - elideWidth - _elideRemoveFromEnd;
int firstItem = engine.findItem(line.from), lastItem = engine.findItem(line.from + line.length - 1);
int nItems = (firstItem >= 0 && lastItem >= firstItem) ? (lastItem - firstItem + 1) : 0, i;
int nItems = (firstItem >= 0 && lastItem >= firstItem) ? (lastItem - firstItem + 1) : 0, i;
for (i = 0; i < nItems; ++i) {
QScriptItem &si(engine.layoutData->items[firstItem + i]);
@ -3214,6 +3214,17 @@ TextForMimeData String::toText(
if (composeExpanded) {
result.expanded.reserve(_text.size());
}
const auto insertEntity = [&](EntityInText &&entity) {
auto i = result.rich.entities.end();
while (i != result.rich.entities.begin()) {
auto j = i;
if ((--j)->offset() <= entity.offset()) {
break;
}
i = j;
}
result.rich.entities.insert(i, std::move(entity));
};
auto linkStart = 0;
auto markdownTrackers = composeEntities
? std::vector<MarkdownTagTracker>{
@ -3231,7 +3242,7 @@ TextForMimeData String::toText(
for (auto &tracker : markdownTrackers) {
const auto flag = tracker.flag;
if ((oldFlags & flag) && !(newFlags & flag)) {
result.rich.entities.push_back({
insertEntity({
tracker.type,
tracker.start,
result.rich.text.size() - tracker.start });
@ -3256,15 +3267,17 @@ TextForMimeData String::toText(
if (!composeExpanded && !composeEntities) {
return;
}
const auto skipLink = (entity.type == EntityType::CustomUrl)
&& (entity.data.startsWith(qstr("internal:")));
if (composeExpanded) {
result.expanded.append(full);
if (entity.type == EntityType::CustomUrl) {
if (entity.type == EntityType::CustomUrl && !skipLink) {
const auto &url = entity.data;
result.expanded.append(qstr(" (")).append(url).append(')');
}
}
if (composeEntities) {
result.rich.entities.push_back({
if (composeEntities && !skipLink) {
insertEntity({
entity.type,
linkStart,
full.size(),

View file

@ -8,8 +8,8 @@
#include "ui/style/style_core.h"
#include <QtWidgets/QApplication>
#include <QtGui/QWindow>
#include <QtGui/QGuiApplication>
#include <QtGui/QtEvents>
#include <array>
@ -82,6 +82,10 @@ void SendPendingEventsRecursive(QWidget *target, bool parentHiddenFlag) {
} // namespace
bool AppInFocus() {
return QApplication::focusWidget() != nullptr;
}
void SendPendingMoveResizeEvents(not_null<QWidget*> target) {
CreateWidgetStateRecursive(target);
SendPendingEventsRecursive(target, !target->isVisible());

View file

@ -98,6 +98,8 @@ inline not_null<std::decay_t<Value>*> AttachAsChild(
std::forward<Value>(value))->value();
}
[[nodiscard]] bool AppInFocus();
[[nodiscard]] inline bool InFocusChain(not_null<const QWidget*> widget) {
if (const auto top = widget->window()) {
if (auto focused = top->focusWidget()) {

View file

@ -3152,6 +3152,10 @@ bool InputField::commitMarkdownReplacement(
cursor.setCharFormat(_defaultCharFormat);
_inner->setTextCursor(cursor);
// Fire the tag to the spellchecker.
_markdownTagApplies.fire({ from, till, -1, -1, false, tag });
return true;
}

View file

@ -330,6 +330,9 @@ public:
auto documentContentsChanges() {
return _documentContentsChanges.events();
}
auto markdownTagApplies() {
return _markdownTagApplies.events();
}
~InputField();
@ -535,6 +538,7 @@ private:
bool _instantReplacesEnabled = true;
rpl::event_stream<DocumentChangeInfo> _documentContentsChanges;
rpl::event_stream<MarkdownTag> _markdownTagApplies;
};

View file

@ -519,7 +519,8 @@ PopupMenu::~PopupMenu() {
delete submenu;
}
if (const auto parent = parentWidget()) {
if (QApplication::focusWidget() != nullptr) {
if (QApplication::focusWidget() != nullptr
&& Ui::InFocusChain(parent->window())) {
ActivateWindowDelayed(parent);
}
}

View file

@ -794,7 +794,7 @@ SettingsSlider {
barFg: color;
barFgActive: color;
labelTop: pixels;
labelFont: font;
labelStyle: TextStyle;
labelFg: color;
labelFgActive: color;
duration: int;
@ -812,7 +812,7 @@ defaultSettingsSlider: SettingsSlider {
barFg: sliderBgInactive;
barFgActive: sliderBgActive;
labelTop: 17px;
labelFont: normalFont;
labelStyle: defaultTextStyle;
labelFg: windowActiveTextFg;
labelFgActive: windowActiveTextFg;
duration: 150;
@ -824,7 +824,7 @@ defaultTabsSlider: SettingsSlider(defaultSettingsSlider) {
barSkip: 0px;
barFg: transparent;
labelTop: 19px;
labelFont: semiboldFont;
labelStyle: semiboldTextStyle;
labelFg: windowSubTextFg;
labelFgActive: lightButtonFg;
rippleBottomSkip: 1px;

View file

@ -77,6 +77,8 @@ public:
return RpWidget::naturalWidth();
}
using WrapParentType = RpWidget;
protected:
int resizeGetHeight(int newWidth) override {
if (auto weak = wrapped()) {