Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
1d2bfb4863
30 changed files with 455 additions and 57 deletions
201
CMakeLists.txt
Normal file
201
CMakeLists.txt
Normal 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
|
||||
)
|
||||
29
cmake/generate_emoji.cmake
Normal file
29
cmake/generate_emoji.cmake
Normal 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()
|
||||
32
cmake/generate_palette.cmake
Normal file
32
cmake/generate_palette.cmake
Normal 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()
|
||||
40
cmake/generate_styles.cmake
Normal file
40
cmake/generate_styles.cmake
Normal 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()
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual QString url() const = 0;
|
||||
virtual QString readable() const {
|
||||
return url();
|
||||
}
|
||||
virtual QString readable() const;
|
||||
|
||||
bool _fullDisplayed;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,5 +43,8 @@ bool TranslucentWindowsSupported(QPoint globalPosition) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void IgnoreAllActivation(not_null<QWidget*> widget) {
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -91,5 +91,8 @@ void DrainMainQueue() {
|
|||
_dispatch_main_queue_callback_4CF(nullptr);
|
||||
}
|
||||
|
||||
void IgnoreAllActivation(not_null<QWidget*> widget) {
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace Ui
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@ public:
|
|||
return QMargins();
|
||||
}
|
||||
|
||||
bool inFocusChain() const {
|
||||
return Ui::InFocusChain(this);
|
||||
}
|
||||
|
||||
void hideChildren() {
|
||||
for (auto child : Base::children()) {
|
||||
if (child->isWidgetType()) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ public:
|
|||
return RpWidget::naturalWidth();
|
||||
}
|
||||
|
||||
using WrapParentType = RpWidget;
|
||||
|
||||
protected:
|
||||
int resizeGetHeight(int newWidth) override {
|
||||
if (auto weak = wrapped()) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue