Compare commits

..

39 Commits

Author SHA1 Message Date
John Preston
ee0400f1ac Version 2.8.2.
- Attempt to fix random crashes on macOS.

Fixes #16504.
2021-06-28 08:57:40 +03:00
John Preston
b8a3746558 Version 2.8.1: Fix NuGet WinRT header generation. 2021-06-26 13:26:39 +03:00
John Preston
14f25fc997 Version 2.8.1.
- Fix crash in audio player volume slider.
2021-06-26 13:03:40 +03:00
John Preston
27da6ee9eb Update patches revision in instructions. 2021-06-26 13:00:16 +03:00
John Preston
48d482006a Fix crash fix. 2021-06-26 12:33:18 +03:00
John Preston
9afee2620a Fix crash in vertical sliders.
Regression was introduced in 90ff8ecd0f.
2021-06-26 08:20:37 +03:00
John Preston
baca3047d4 Version 2.8: Fix build on Windows x64. 2021-06-24 18:39:41 +04:00
John Preston
43a5265e0c Version 2.8.
- Start video conferences from Voice Chats in any group.
- Share your screen or video from your camera
with up to 30 participants (limit to be increased soon).
- Talk without video with an unlimited number of participants.
- Create voice chats from the info page
of any group where you are an admin.
- Group video calls are supported natively on all devices,
including iPads and laptops.
2021-06-24 17:57:09 +04:00
John Preston
5519bb3523 Allow reporting private groups as well.
Fixes #7451.
2021-06-24 17:44:55 +04:00
John Preston
ff213d1386 Enable /LARGEADDRESSAWARE for 32 bit Windows build. 2021-06-24 17:44:55 +04:00
John Preston
55b3f99653 Fix new formatting mixing with emoji. 2021-06-24 17:44:55 +04:00
John Preston
8a6ff3f414 Add separator above volume control in voice chats. 2021-06-24 17:44:55 +04:00
John Preston
feb8624d05 Don't use private Hunspell headers. 2021-06-24 17:44:55 +04:00
John Preston
a2c33545d4 Improve some paddings. 2021-06-24 17:44:28 +04:00
23rd
7decf68122 Fixed possible crash in OverlayWidget when video continues from PiP. 2021-06-24 17:44:28 +04:00
John Preston
6b62ec97c6 Fix possible crash in export panel management. 2021-06-24 11:57:27 +04:00
Ilya Fedin
ea3dab4a06 Update lib_base 2021-06-24 11:26:24 +04:00
Ilya Fedin
5c8f08fc92 Move preview support from QGtkDialog to GtkFileDialog 2021-06-24 11:26:24 +04:00
Ilya Fedin
00a0b2c8b6 Get rid of GTK cast templates 2021-06-24 11:26:24 +04:00
Ilya Fedin
007218cc13 Use C++ wrappers in GtkOpenWithDialog 2021-06-24 11:26:24 +04:00
Ilya Fedin
8afe495a4f Avoid using g_unix_fd_list_new_from_array 2021-06-24 11:26:24 +04:00
Ilya Fedin
257f2086d1 Get rid of gtk2 header compatibility 2021-06-24 11:26:24 +04:00
Ilya Fedin
f011c84ce8 Make Linux file dialog API better 2021-06-24 11:26:24 +04:00
Ilya Fedin
8b839f46b2 Fix crash report window scale 2021-06-24 11:26:08 +04:00
23rd
c1067d8fe1 Fixed possible crash in notifications manager. 2021-06-24 11:25:36 +04:00
23rd
bb76818cc8 Split adaptive changed rpl::producer into two. 2021-06-24 11:25:35 +04:00
John Preston
5dcc219f1c For large video tile always request full quality. 2021-06-24 10:57:23 +04:00
John Preston
4ff9e90153 Add some assertions and logging for a crash debugging. 2021-06-24 10:49:01 +04:00
John Preston
28fe98af80 Add some assertions for a strange crash debugging. 2021-06-24 10:24:52 +04:00
John Preston
5eba65aaa0 Remove unused legacy protocol code. 2021-06-24 09:55:57 +04:00
John Preston
d1e3e7d240 Don't show pinned tooltips if only one video. 2021-06-23 20:14:49 +04:00
John Preston
90ff8ecd0f Fix volume slider in voice chats. 2021-06-23 20:14:22 +04:00
John Preston
468e75a572 Update submodules. 2021-06-23 20:13:19 +04:00
John Preston
ae3e5487d7 Fix editing messages with monospace parts. 2021-06-23 15:55:29 +04:00
John Preston
03147a5426 Fix possible crash in case of API error. 2021-06-23 14:29:38 +04:00
John Preston
14a2b10989 Show error if camera could not be enabled. 2021-06-23 12:04:05 +04:00
John Preston
b29f8aa1e6 Remove background over highlight in volume change item. 2021-06-23 11:07:23 +04:00
John Preston
f9bb932cd8 Fix voice chat window expanding near the screen edges. 2021-06-23 10:52:04 +04:00
John Preston
a38cbbf7e8 Fix disappearing icons after popup menu display. 2021-06-23 10:43:51 +04:00
72 changed files with 395 additions and 411 deletions

View File

@@ -125,7 +125,7 @@ if (LINUX)
target_link_libraries(Telegram PRIVATE PkgConfig::X11)
endif()
else()
pkg_search_module(GTK REQUIRED gtk+-3.0 gtk+-2.0)
pkg_check_modules(GTK REQUIRED gtk+-3.0)
target_include_directories(Telegram PRIVATE ${GTK_INCLUDE_DIRS})
if (NOT DESKTOP_APP_DISABLE_X11_INTEGRATION)

View File

@@ -1007,6 +1007,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_report_group_title" = "Report group";
"lng_report_bot_title" = "Report bot";
"lng_report_message_title" = "Report message";
"lng_report_please_select_messages" = "Please select messages to report.";
"lng_report_select_messages" = "Select messages";
"lng_report_messages_none" = "Select Messages";
"lng_report_messages_count#one" = "Report {count} Message";
@@ -2030,6 +2031,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_group_call_chat_no_camera" = "You can't turn on video in this chat.";
"lng_group_call_chat_no_screen" = "You can't share your screen in this chat.";
"lng_group_call_failed_screen" = "An error occured. Screencast has stopped.";
"lng_group_call_failed_camera" = "Could not enable camera. Perhaps another app is using the camera already. Try closing other apps.";
"lng_group_call_tooltip_screen" = "Share screen";
"lng_group_call_tooltip_camera" = "Your camera is off. Click here to enable camera.";
"lng_group_call_tooltip_microphone" = "You are on mute. Click here to speak.";

View File

@@ -9,7 +9,7 @@
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
ProcessorArchitecture="ARCHITECTURE"
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
Version="2.7.10.0" />
Version="2.8.2.0" />
<Properties>
<DisplayName>Telegram Desktop</DisplayName>
<PublisherDisplayName>Telegram Messenger LLP</PublisherDisplayName>

View File

@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,7,10,0
PRODUCTVERSION 2,7,10,0
FILEVERSION 2,8,2,0
PRODUCTVERSION 2,8,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -62,10 +62,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop"
VALUE "FileVersion", "2.7.10.0"
VALUE "FileVersion", "2.8.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.7.10.0"
VALUE "ProductVersion", "2.8.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,7,10,0
PRODUCTVERSION 2,7,10,0
FILEVERSION 2,8,2,0
PRODUCTVERSION 2,8,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -53,10 +53,10 @@ BEGIN
BEGIN
VALUE "CompanyName", "Telegram FZ-LLC"
VALUE "FileDescription", "Telegram Desktop Updater"
VALUE "FileVersion", "2.7.10.0"
VALUE "FileVersion", "2.8.2.0"
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
VALUE "ProductName", "Telegram Desktop"
VALUE "ProductVersion", "2.7.10.0"
VALUE "ProductVersion", "2.8.2.0"
END
END
BLOCK "VarFileInfo"

View File

@@ -520,6 +520,10 @@ groupCallPopupMenuWithVolume: PopupMenu(groupCallPopupMenu) {
widthMin: 210px;
}
}
groupCallPopupVolumeMenu: Menu(groupCallMenu) {
widthMin: 210px;
itemBgOver: groupCallMenuBg;
}
groupCallRecordingTimerPadding: margins(0px, 4px, 0px, 4px);
groupCallRecordingTimerFont: font(12px);

View File

@@ -1989,6 +1989,10 @@ bool GroupCall::emitShareCameraError() {
void GroupCall::emitShareCameraError(Error error) {
_cameraState = Webrtc::VideoState::Inactive;
if (error == Error::CameraFailed
&& Webrtc::GetVideoInputList().empty()) {
error = Error::NoCamera;
}
_errors.fire_copy(error);
}
@@ -2042,8 +2046,14 @@ void GroupCall::setupOutgoingVideo() {
_cameraCapture = _delegate->groupCallGetVideoCapture(
_cameraInputId);
if (!_cameraCapture) {
return emitShareCameraError(Error::NoCamera);
return emitShareCameraError(Error::CameraFailed);
}
const auto weak = base::make_weak(this);
_cameraCapture->setOnFatalError([=] {
crl::on_main(weak, [=] {
emitShareCameraError(Error::CameraFailed);
});
});
} else {
_cameraCapture->switchToDevice(_cameraInputId.toStdString());
}

View File

@@ -61,6 +61,7 @@ enum class VideoQuality {
enum class Error {
NoCamera,
CameraFailed,
ScreenFailed,
MutedNoCamera,
MutedNoScreen,

View File

@@ -1455,7 +1455,7 @@ void Members::Controller::addMuteActionsToContextMenu(
auto volumeItem = base::make_unique_q<MenuVolumeItem>(
menu->menu(),
st::groupCallPopupMenuWithVolume.menu,
st::groupCallPopupVolumeMenu,
otherParticipantStateValue,
row->volume(),
Group::kMaxVolume,
@@ -1494,6 +1494,10 @@ void Members::Controller::addMuteActionsToContextMenu(
}
}, volumeItem->lifetime());
if (!menu->empty()) {
menu->addSeparator();
}
menu->addAction(std::move(volumeItem));
if (!isMe(participantPeer)) {

View File

@@ -841,19 +841,19 @@ void Panel::enlargeVideo() {
std::min(available.height(), st::groupCallWideModeSize.height()));
auto geometry = QRect(window()->pos(), QSize(width, height));
if (geometry.x() < available.x()) {
geometry.setX(std::min(available.x(), window()->x()));
geometry.moveLeft(std::min(available.x(), window()->x()));
}
if (geometry.x() + geometry.width()
> available.x() + available.width()) {
geometry.setX(std::max(
geometry.moveLeft(std::max(
available.x() + available.width(),
window()->x() + window()->width()) - geometry.width());
}
if (geometry.y() < available.y()) {
geometry.setY(std::min(available.y(), window()->y()));
geometry.moveTop(std::min(available.y(), window()->y()));
}
if (geometry.y() + geometry.height() > available.y() + available.height()) {
geometry.setY(std::max(
geometry.moveTop(std::max(
available.y() + available.height(),
window()->y() + window()->height()) - geometry.height());
}

View File

@@ -105,7 +105,9 @@ void Toasts::setupPinnedVideo() {
? _call->videoEndpointLargeValue()
: rpl::single(_call->videoEndpointLarge());
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
) | rpl::filter([=] {
return (_call->shownVideoTracks().size() > 1);
}) | rpl::start_with_next([=](const VideoEndpoint &endpoint) {
const auto pinned = _call->videoEndpointPinned();
const auto peer = endpoint.peer;
if (!peer) {
@@ -155,6 +157,8 @@ void Toasts::setupError() {
const auto key = [&] {
switch (error) {
case Error::NoCamera: return tr::lng_call_error_no_camera;
case Error::CameraFailed:
return tr::lng_group_call_failed_camera;
case Error::ScreenFailed:
return tr::lng_group_call_failed_screen;
case Error::MutedNoCamera:

View File

@@ -765,9 +765,10 @@ void Viewport::setTileGeometry(not_null<VideoTile*> tile, QRect geometry) {
const auto &endpoint = tile->endpoint();
const auto forceThumbnailQuality = !wide()
&& (ranges::count(_tiles, false, &VideoTile::hidden) > 1);
const auto forceFullQuality = wide() && (tile.get() == _large);
const auto quality = forceThumbnailQuality
? VideoQuality::Thumbnail
: (min >= kMedium)
: (forceFullQuality || min >= kMedium)
? VideoQuality::Full
: (min >= kSmall)
? VideoQuality::Medium

View File

@@ -744,7 +744,7 @@ FieldAutocomplete::Inner::Inner(
update();
}, lifetime());
controller->adaptive().changed(
controller->adaptive().value(
) | rpl::start_with_next([=] {
_isOneColumn = controller->adaptive().isOneColumn();
update();

View File

@@ -95,6 +95,9 @@ public:
[[nodiscard]] rpl::producer<bool> adaptiveForWideValue() const {
return _adaptiveForWide.value();
}
[[nodiscard]] rpl::producer<bool> adaptiveForWideChanges() const {
return _adaptiveForWide.changes();
}
void setAdaptiveForWide(bool value) {
_adaptiveForWide = value;
}

View File

@@ -183,8 +183,6 @@ void Sandbox::launchApplication() {
}
void Sandbox::setupScreenScale() {
Ui::DisableCustomScaling();
const auto dpi = Sandbox::primaryScreen()->logicalDotsPerInch();
LOG(("Primary screen DPI: %1").arg(dpi));
if (dpi <= 108) {
@@ -315,6 +313,7 @@ void Sandbox::singleInstanceChecked() {
Logs::multipleInstances();
}
Ui::DisableCustomScaling();
refreshGlobalProxy();
if (!Logs::started() || (!cManyInstance() && !Logs::instanceChecked())) {
new NotStartedWindow();

View File

@@ -22,7 +22,7 @@ constexpr auto AppId = "{53F49750-6209-4FBF-9CA8-7A333C87D1ED}"_cs;
constexpr auto AppNameOld = "Telegram Win (Unofficial)"_cs;
constexpr auto AppName = "Telegram Desktop"_cs;
constexpr auto AppFile = "Telegram"_cs;
constexpr auto AppVersion = 2007010;
constexpr auto AppVersionStr = "2.7.10";
constexpr auto AppBetaVersion = true;
constexpr auto AppVersion = 2008002;
constexpr auto AppVersionStr = "2.8.2";
constexpr auto AppBetaVersion = false;
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;

View File

@@ -209,7 +209,7 @@ base::binary_guard ReadImageAsync(
}
void ResolveDocument(
not_null<Window::SessionController*> controller,
Window::SessionController *controller,
not_null<DocumentData*> document,
HistoryItem *item) {
if (!document->date) {
@@ -222,7 +222,7 @@ void ResolveDocument(
&& document->isVideoFile()
&& !document->filepath().isEmpty()) {
File::Launch(document->location(false).fname);
} else {
} else if (controller) {
controller->openDocument(document, msgId, true);
}
};

View File

@@ -30,7 +30,7 @@ base::binary_guard ReadImageAsync(
FnMut<void(QImage&&)> done);
void ResolveDocument(
not_null<Window::SessionController*> controller,
Window::SessionController *controller,
not_null<DocumentData*> document,
HistoryItem *item);

View File

@@ -2138,7 +2138,7 @@ void InnerWidget::peerSearchReceived(
} else {
LOG(("API Error: "
"user %1 was not loaded in InnerWidget::peopleReceived()"
).arg(peer->id.value));
).arg(peerFromMTP(mtpPeer).value));
}
}
for (const auto &mtpPeer : result) {
@@ -2153,7 +2153,7 @@ void InnerWidget::peerSearchReceived(
} else {
LOG(("API Error: "
"user %1 was not loaded in InnerWidget::peopleReceived()"
).arg(peer->id.value));
).arg(peerFromMTP(mtpPeer).value));
}
}
refresh();

View File

@@ -266,7 +266,7 @@ Widget::Widget(
}, lifetime());
}
controller->adaptive().changed(
controller->adaptive().changes(
) | rpl::start_with_next([=] {
updateForwardBar();
}, lifetime());

View File

@@ -153,11 +153,15 @@ PanelController::~PanelController() {
if (_saveSettingsTimer.isActive()) {
saveSettings();
}
_panel->destroyLayer();
if (_panel) {
_panel->destroyLayer();
}
}
void PanelController::activatePanel() {
_panel->showAndActivate();
if (_panel) {
_panel->showAndActivate();
}
}
void PanelController::createPanel() {

View File

@@ -298,10 +298,7 @@ Widget::Widget(
_fixedBarShadow->raise();
rpl::single(
rpl::empty_value()
) | rpl::then(
controller->adaptive().changed()
controller->adaptive().value(
) | rpl::start_with_next([=] {
updateAdaptiveLayout();
}, lifetime());

View File

@@ -413,7 +413,7 @@ HistoryWidget::HistoryWidget(
Window::ActivateWindow(controller);
});
controller->adaptive().changed(
controller->adaptive().changes(
) | rpl::start_with_next([=] {
if (_history) {
_history->forceFullResize();

View File

@@ -128,10 +128,7 @@ PinnedWidget::PinnedWidget(
}, _topBar->lifetime());
_topBarShadow->raise();
rpl::single(
rpl::empty_value()
) | rpl::then(
controller->adaptive().changed()
controller->adaptive().value(
) | rpl::start_with_next([=] {
updateAdaptiveLayout();
}, lifetime());

View File

@@ -193,10 +193,7 @@ RepliesWidget::RepliesWidget(
_rootView->raise();
_topBarShadow->raise();
rpl::single(
rpl::empty_value()
) | rpl::then(
controller->adaptive().changed()
controller->adaptive().value(
) | rpl::start_with_next([=] {
updateAdaptiveLayout();
}, lifetime());

View File

@@ -126,10 +126,7 @@ ScheduledWidget::ScheduledWidget(
}, _topBar->lifetime());
_topBarShadow->raise();
rpl::single(
rpl::empty_value()
) | rpl::then(
controller->adaptive().changed()
controller->adaptive().value(
) | rpl::start_with_next([=] {
updateAdaptiveLayout();
}, lifetime());

View File

@@ -117,7 +117,7 @@ TopBarWidget::TopBarWidget(
_search->setForceRippled(searchInActiveChat, animated);
}, lifetime());
controller->adaptive().changed(
controller->adaptive().changes(
) | rpl::start_with_next([=] {
updateAdaptiveLayout();
}, lifetime());

View File

@@ -35,7 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/special_buttons.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/shadow.h"
#include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h"
#include "ui/widgets/dropdown_menu.h"
#include "ui/image/image.h"
#include "ui/focus_persister.h"
@@ -380,7 +380,7 @@ MainWidget::MainWidget(
}
});
_controller->adaptive().changed(
_controller->adaptive().changes(
) | rpl::start_with_next([=] {
handleAdaptiveLayoutUpdate();
}, lifetime());
@@ -1423,6 +1423,9 @@ void MainWidget::showChooseReportMessages(
peer->id,
SectionShow::Way::Forward,
ShowForChooseMessagesMsgId);
Ui::ShowMultilineToast({
.text = { tr::lng_report_please_select_messages(tr::now) },
});
}
void MainWidget::clearChooseReportMessages() {

View File

@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ffmpeg/ffmpeg_utility.h"
#include "media/audio/media_audio.h"
#include "base/concurrent_timer.h"
#include "core/crash_reports.h"
namespace Media {
namespace Streaming {
@@ -288,6 +289,7 @@ void VideoTrackObject::readFrames() {
}
}, [&](Shared::PrepareNextCheck delay) {
Expects(delay == kTimeUnknown || delay > 0);
if (delay != kTimeUnknown) {
queueReadFrames(delay);
}
@@ -303,7 +305,8 @@ auto VideoTrackObject::readEnoughFrames(crl::time trackTime)
-> ReadEnoughState {
const auto dropStaleFrames = !_options.waitForMarkAsShown;
const auto state = _shared->prepareState(trackTime, dropStaleFrames);
return v::match(state, [&](Shared::PrepareFrame frame) -> ReadEnoughState {
return v::match(state, [&](Shared::PrepareFrame frame)
-> ReadEnoughState {
while (true) {
const auto result = readFrame(frame);
if (result != FrameResult::Done) {
@@ -314,6 +317,8 @@ auto VideoTrackObject::readEnoughFrames(crl::time trackTime)
}
}
}, [&](Shared::PrepareNextCheck delay) -> ReadEnoughState {
Expects(delay == kTimeUnknown || delay > 0); // Debugging crash.
return delay;
}, [&](v::null_t) -> ReadEnoughState {
return FrameResult::Done;
@@ -752,6 +757,16 @@ auto VideoTrack::Shared::prepareState(
next->displayed = kDisplaySkipped;
return next;
} else {
if (frame->position - trackTime + 1 <= 0) { // Debugging crash.
CrashReports::SetAnnotation(
"DelayValues",
(QString::number(frame->position)
+ " + 1 <= "
+ QString::number(trackTime)));
}
Assert(frame->position >= trackTime);
Assert(frame->position - trackTime + 1 > 0);
return PrepareNextCheck(frame->position - trackTime + 1);
}
};

View File

@@ -1427,12 +1427,15 @@ void OverlayWidget::subscribeToScreenGeometry() {
}
void OverlayWidget::toMessage() {
if (!_session || !_controller) {
if (!_session) {
return;
}
if (const auto item = _session->data().message(_msgid)) {
close();
_controller->showPeerHistoryAtItem(item);
if (const auto window = findWindow()) {
window->showPeerHistoryAtItem(item);
}
}
}
@@ -1556,11 +1559,8 @@ void OverlayWidget::handleDocumentClick() {
if (_document->loading()) {
saveCancel();
} else {
if (!_controller) {
return;
}
Data::ResolveDocument(
_controller,
findWindow(),
_document,
_document->owner().message(_msgid));
if (_document->loading() && !_radial.animating()) {
@@ -2251,10 +2251,6 @@ void OverlayWidget::activate() {
}
void OverlayWidget::show(OpenRequest request) {
if (!request.controller()) {
return;
}
const auto document = request.document();
const auto photo = request.photo();
const auto contextItem = request.item();
@@ -2264,8 +2260,6 @@ void OverlayWidget::show(OpenRequest request) {
return;
}
setSession(&photo->session());
_controller = request.controller();
Assert(_session == (&_controller->session()));
if (contextPeer) {
setContext(contextPeer);
@@ -2284,8 +2278,6 @@ void OverlayWidget::show(OpenRequest request) {
activateControls();
} else if (document) {
setSession(&document->session());
_controller = request.controller();
Assert(_session == (&_controller->session()));
if (contextItem) {
setContext(contextItem);
@@ -2308,6 +2300,9 @@ void OverlayWidget::show(OpenRequest request) {
activateControls();
}
}
if (const auto controller = request.controller()) {
_window = base::make_weak(&controller->window());
}
}
void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item) {
@@ -3097,14 +3092,13 @@ float64 OverlayWidget::playbackControlsCurrentSpeed() {
void OverlayWidget::switchToPip() {
Expects(_streamed != nullptr);
Expects(_document != nullptr);
Expects(_controller != nullptr);
const auto document = _document;
const auto msgId = _msgid;
const auto closeAndContinue = [=] {
_showAsPip = false;
show(OpenRequest(
_controller,
findWindow(),
document,
document->owner().message(msgId),
true));
@@ -4538,6 +4532,36 @@ void OverlayWidget::applyHideWindowWorkaround() {
}
}
Window::SessionController *OverlayWidget::findWindow() const {
if (!_session) {
return nullptr;
}
const auto window = _window.get();
if (window) {
if (const auto controller = window->sessionController()) {
if (&controller->session() == _session) {
return controller;
}
}
}
const auto &active = _session->windows();
if (!active.empty()) {
return active.front();
} else if (window) {
Window::SessionController *controllerPtr = nullptr;
window->invokeForSessionController(
&_session->account(),
[&](not_null<Window::SessionController*> newController) {
controllerPtr = newController;
});
return controllerPtr;
}
return nullptr;
}
// #TODO unite and check
void OverlayWidget::clearBeforeHide() {
_sharedMedia = nullptr;

View File

@@ -411,11 +411,13 @@ private:
void applyHideWindowWorkaround();
Window::SessionController *findWindow() const;
bool _opengl = false;
const std::unique_ptr<Ui::RpWidgetWrap> _surface;
const not_null<QWidget*> _widget;
Window::SessionController *_controller = nullptr;
base::weak_ptr<Window::Controller> _window;
Main::Session *_session = nullptr;
rpl::lifetime _sessionLifetime;
PhotoData *_photo = nullptr;

View File

@@ -1009,6 +1009,9 @@ void Pip::handleMousePress(QPoint position, Qt::MouseButton button) {
}
void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
Expects(1 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
const auto weak = Ui::MakeWeak(_panel.widget());
const auto guard = gsl::finally([&] {
if (weak) {
@@ -1019,10 +1022,22 @@ void Pip::handleMouseRelease(QPoint position, Qt::MouseButton button) {
return;
}
seekUpdate(position);
Assert(2 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
volumeControllerUpdate(position);
Assert(3 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
const auto pressed = base::take(_pressed);
if (pressed && *pressed == OverState::Playback) {
_panel.setDragDisabled(false);
Assert(4 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
seekFinish(_playbackProgress->value());
} else if (pressed && *pressed == OverState::VolumeController) {
_panel.setDragDisabled(false);
@@ -1083,6 +1098,9 @@ void Pip::seekProgress(float64 value) {
}
void Pip::seekFinish(float64 value) {
Expects(5 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
if (!_lastDurationMs) {
return;
}
@@ -1556,15 +1574,30 @@ void Pip::playbackPauseResume() {
}
void Pip::restartAtSeekPosition(crl::time position) {
Expects(6 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
if (!_instance.info().video.cover.isNull()) {
_preparedCoverStorage = QImage();
_preparedCoverState = ThumbState::Empty;
_instance.saveFrameToCover();
}
Assert(7 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
auto options = Streaming::PlaybackOptions();
options.position = position;
options.audioId = _instance.player().prepareLegacyState().id;
Assert(8 && _delegate->pipPlaybackSpeed() >= 0.5
&& _delegate->pipPlaybackSpeed() <= 2.); // Debugging strange crash.
options.speed = _delegate->pipPlaybackSpeed();
Assert(9 && options.speed >= 0.5
&& options.speed <= 2.); // Debugging strange crash.
_instance.play(options);
if (_startPaused) {
_instance.pause();

View File

@@ -189,9 +189,7 @@ ConnectionPointer AbstractConnection::Create(
}
uint32 AbstractConnection::extendedNotSecurePadding() const {
return requiresExtendedPadding()
? uint32(openssl::RandomValue<uchar>() & 0x3F)
: 0;
return uint32(openssl::RandomValue<uchar>() & 0x3F);
}
} // namespace details

View File

@@ -92,9 +92,6 @@ public:
[[nodiscard]] virtual bool needHttpWait() {
return false;
}
[[nodiscard]] virtual bool requiresExtendedPadding() const {
return false;
}
[[nodiscard]] virtual int32 debugState() const = 0;

View File

@@ -198,12 +198,6 @@ void ResolvingConnection::sendData(mtpBuffer &&buffer) {
_child->sendData(std::move(buffer));
}
bool ResolvingConnection::requiresExtendedPadding() const {
Expects(_child != nullptr);
return _child->requiresExtendedPadding();
}
void ResolvingConnection::disconnectFromServer() {
_address = QString();
_port = 0;

View File

@@ -35,7 +35,6 @@ public:
int16 protocolDcId,
bool protocolForFiles) override;
bool isConnected() const override;
bool requiresExtendedPadding() const override;
int32 debugState() const override;

View File

@@ -35,7 +35,6 @@ public:
virtual uint32 id() const = 0;
virtual bool supportsArbitraryLength() const = 0;
virtual bool requiresExtendedPadding() const = 0;
virtual void prepareKey(bytes::span key, bytes::const_span source) = 0;
virtual bytes::span finalizePacket(mtpBuffer &buffer) = 0;
@@ -58,7 +57,6 @@ public:
uint32 id() const override;
bool supportsArbitraryLength() const override;
bool requiresExtendedPadding() const override;
void prepareKey(bytes::span key, bytes::const_span source) override;
bytes::span finalizePacket(mtpBuffer &buffer) override;
@@ -75,10 +73,6 @@ bool TcpConnection::Protocol::Version0::supportsArbitraryLength() const {
return false;
}
bool TcpConnection::Protocol::Version0::requiresExtendedPadding() const {
return false;
}
void TcpConnection::Protocol::Version0::prepareKey(
bytes::span key,
bytes::const_span source) {
@@ -142,7 +136,6 @@ class TcpConnection::Protocol::Version1 : public Version0 {
public:
explicit Version1(bytes::vector &&secret);
bool requiresExtendedPadding() const override;
void prepareKey(bytes::span key, bytes::const_span source) override;
private:
@@ -154,10 +147,6 @@ TcpConnection::Protocol::Version1::Version1(bytes::vector &&secret)
: _secret(std::move(secret)) {
}
bool TcpConnection::Protocol::Version1::requiresExtendedPadding() const {
return true;
}
void TcpConnection::Protocol::Version1::prepareKey(
bytes::span key,
bytes::const_span source) {
@@ -425,12 +414,6 @@ void TcpConnection::socketDisconnected() {
}
}
bool TcpConnection::requiresExtendedPadding() const {
Expects(_protocol != nullptr);
return _protocol->requiresExtendedPadding();
}
void TcpConnection::sendData(mtpBuffer &&buffer) {
Expects(buffer.size() > 2);

View File

@@ -36,7 +36,6 @@ public:
bool protocolForFiles) override;
void timedOut() override;
bool isConnected() const override;
bool requiresExtendedPadding() const override;
int32 debugState() const override;

View File

@@ -25,7 +25,7 @@ namespace {
auto serialized = SerializedRequest::Serialize(data);
serialized.setMsgId(realMsgId);
serialized.setSeqNo(0);
serialized.addPadding(false, true);
serialized.addPadding(true);
constexpr auto kMsgIdPosition = SerializedRequest::kMessageIdPosition;
constexpr auto kMinMessageSize = 5;

View File

@@ -12,8 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace MTP::details {
namespace {
uint32 CountPaddingPrimesCount(uint32 requestSize, bool extended, bool old) {
if (old) {
uint32 CountPaddingPrimesCount(
uint32 requestSize,
bool forAuthKeyInner) {
if (forAuthKeyInner) {
return ((8 + requestSize) & 0x03)
? (4 - ((8 + requestSize) & 0x03))
: 0;
@@ -27,12 +29,8 @@ uint32 CountPaddingPrimesCount(uint32 requestSize, bool extended, bool old) {
result += 4;
}
if (extended) {
// Some more random padding.
result += ((openssl::RandomValue<uchar>() & 0x0F) << 2);
}
return result;
// Some more random padding.
return result + ((openssl::RandomValue<uchar>() & 0x0F) << 2);
}
} // namespace
@@ -100,12 +98,14 @@ uint32 SerializedRequest::getSeqNo() const {
return uint32((*_data)[kSeqNoPosition]);
}
void SerializedRequest::addPadding(bool extended, bool old) {
void SerializedRequest::addPadding(bool forAuthKeyInner) {
Expects(_data != nullptr);
Expects(_data->size() > kMessageBodyPosition);
const auto requestSize = (tl::count_length(*this) >> 2);
const auto padding = CountPaddingPrimesCount(requestSize, extended, old);
const auto padding = CountPaddingPrimesCount(
requestSize,
forAuthKeyInner);
const auto fullSize = kMessageBodyPosition + requestSize + padding;
if (uint32(_data->size()) != fullSize) {
_data->resize(fullSize);

View File

@@ -65,7 +65,7 @@ public:
void setSeqNo(uint32 seqNo);
[[nodiscard]] uint32 getSeqNo() const;
void addPadding(bool extended, bool old);
void addPadding(bool forAuthKeyInner);
[[nodiscard]] uint32 messageSize() const;
[[nodiscard]] bool needAck() const;

View File

@@ -1263,17 +1263,16 @@ void SessionPrivate::handleReceived() {
return restart();
}
constexpr auto kMinPaddingSize = 12U;
constexpr auto kMaxPaddingSize = 1024U;
auto encryptedInts = ints + kExternalHeaderIntsCount;
auto encryptedIntsCount = (intsCount - kExternalHeaderIntsCount) & ~0x03U;
auto encryptedBytesCount = encryptedIntsCount * kIntSize;
auto decryptedBuffer = QByteArray(encryptedBytesCount, Qt::Uninitialized);
auto msgKey = *(MTPint128*)(ints + 2);
#ifdef TDESKTOP_MTPROTO_OLD
aesIgeDecrypt_oldmtp(encryptedInts, decryptedBuffer.data(), encryptedBytesCount, _encryptionKey, msgKey);
#else // TDESKTOP_MTPROTO_OLD
aesIgeDecrypt(encryptedInts, decryptedBuffer.data(), encryptedBytesCount, _encryptionKey, msgKey);
#endif // TDESKTOP_MTPROTO_OLD
auto decryptedInts = reinterpret_cast<const mtpPrime*>(decryptedBuffer.constData());
auto serverSalt = *(uint64*)&decryptedInts[0];
@@ -1283,31 +1282,10 @@ void SessionPrivate::handleReceived() {
auto needAck = ((seqNo & 0x01) != 0);
auto messageLength = *(uint32*)&decryptedInts[7];
auto fullDataLength = kEncryptedHeaderIntsCount * kIntSize + messageLength; // Without padding.
auto badMessageLength = (messageLength > kMaxMessageLength);
// Can underflow, but it is an unsigned type, so we just check the range later.
auto paddingSize = static_cast<uint32>(encryptedBytesCount) - static_cast<uint32>(fullDataLength);
#ifdef TDESKTOP_MTPROTO_OLD
constexpr auto kMinPaddingSize_oldmtp = 0U;
constexpr auto kMaxPaddingSize_oldmtp = 15U;
badMessageLength |= (/*paddingSize < kMinPaddingSize_oldmtp || */paddingSize > kMaxPaddingSize_oldmtp);
auto hashedDataLength = badMessageLength ? encryptedBytesCount : fullDataLength;
auto sha1ForMsgKeyCheck = hashSha1(decryptedInts, hashedDataLength);
constexpr auto kMsgKeyShift_oldmtp = 4U;
if (ConstTimeIsDifferent(&msgKey, sha1ForMsgKeyCheck.data() + kMsgKeyShift_oldmtp, sizeof(msgKey))) {
LOG(("TCP Error: bad SHA1 hash after aesDecrypt in message."));
TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str()));
return restart();
}
#else // TDESKTOP_MTPROTO_OLD
constexpr auto kMinPaddingSize = 12U;
constexpr auto kMaxPaddingSize = 1024U;
badMessageLength |= (paddingSize < kMinPaddingSize || paddingSize > kMaxPaddingSize);
std::array<uchar, 32> sha256Buffer = { { 0 } };
SHA256_CTX msgKeyLargeContext;
@@ -1323,9 +1301,11 @@ void SessionPrivate::handleReceived() {
return restart();
}
#endif // TDESKTOP_MTPROTO_OLD
if (badMessageLength || (messageLength & 0x03)) {
if ((messageLength > kMaxMessageLength)
|| (messageLength & 0x03)
|| (paddingSize < kMinPaddingSize)
|| (paddingSize > kMaxPaddingSize)) {
LOG(("TCP Error: bad msg_len received %1, data size: %2").arg(messageLength).arg(encryptedBytesCount));
TCP_LOG(("TCP Error: bad message %1").arg(Logs::mb(encryptedInts, encryptedBytesCount).str()));
@@ -2616,12 +2596,7 @@ void SessionPrivate::destroyTemporaryKey() {
bool SessionPrivate::sendSecureRequest(
SerializedRequest &&request,
bool needAnyResponse) {
#ifdef TDESKTOP_MTPROTO_OLD
const auto oldPadding = true;
#else // TDESKTOP_MTPROTO_OLD
const auto oldPadding = false;
#endif // TDESKTOP_MTPROTO_OLD
request.addPadding(_connection->requiresExtendedPadding(), oldPadding);
request.addPadding(false);
uint32 fullSize = request->size();
if (fullSize < 9) {
@@ -2643,27 +2618,6 @@ bool SessionPrivate::sendSecureRequest(
).arg(getProtocolDcId()
).arg(_encryptionKey->keyId()));
#ifdef TDESKTOP_MTPROTO_OLD
uint32 padding = fullSize - 4 - messageSize;
uchar encryptedSHA[20];
MTPint128 &msgKey(*(MTPint128*)(encryptedSHA + 4));
hashSha1(
request->constData(),
(fullSize - padding) * sizeof(mtpPrime),
encryptedSHA);
auto packet = _connection->prepareSecurePacket(_keyId, msgKey, fullSize);
const auto prefix = packet.size();
packet.resize(prefix + fullSize);
aesIgeEncrypt_oldmtp(
request->constData(),
&packet[prefix],
fullSize * sizeof(mtpPrime),
_encryptionKey,
msgKey);
#else // TDESKTOP_MTPROTO_OLD
uchar encryptedSHA256[32];
MTPint128 &msgKey(*(MTPint128*)(encryptedSHA256 + 8));
@@ -2683,7 +2637,6 @@ bool SessionPrivate::sendSecureRequest(
fullSize * sizeof(mtpPrime),
_encryptionKey,
msgKey);
#endif // TDESKTOP_MTPROTO_OLD
DEBUG_LOG(("MTP Info: sending request, size: %1, num: %2, time: %3").arg(fullSize + 6).arg((*request)[4]).arg((*request)[5]));

View File

@@ -171,7 +171,7 @@ bool Get(
parent = parent->window();
}
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
if (XDP::Use(type)) {
{
const auto result = XDP::Get(
parent,
files,
@@ -187,15 +187,17 @@ bool Get(
}
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
if (const auto integration = GtkIntegration::Instance()) {
if (integration->useFileDialog(type)) {
return integration->getFileDialog(
parent,
files,
remoteContent,
caption,
filter,
type,
startFile);
const auto result = integration->getFileDialog(
parent,
files,
remoteContent,
caption,
filter,
type,
startFile);
if (result.has_value()) {
return *result;
}
}
// avoid situation when portals don't work

View File

@@ -20,13 +20,11 @@ extern "C" {
} // extern "C"
#endif // !DESKTOP_APP_DISABLE_X11_INTEGRATION
// CentOS 7 seem to be too old for needed definitions,
// so don't include until we link to gtk directly.
#if !defined DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION && defined LINK_TO_GTK
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
extern "C" {
#include <gdk/gdkwayland.h>
} // extern "C"
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION && LINK_TO_GTK
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
namespace Platform {
namespace internal {
@@ -36,7 +34,7 @@ using base::Platform::GtkIntegration;
using namespace Platform::Gtk;
#ifndef DESKTOP_APP_DISABLE_X11_INTEGRATION
// To be able to compile with gtk-3.0 headers as well
// To be able to compile with gtk-3.0 headers
#define GdkDrawable GdkWindow
// Gtk 2
@@ -50,12 +48,6 @@ f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr;
using f_gdk_x11_window_get_type = GType (*)(void);
f_gdk_x11_window_get_type gdk_x11_window_get_type = nullptr;
// To be able to compile with gtk-2.0 headers as well
template <typename Object>
inline bool gdk_is_x11_window_check(Object *obj) {
return g_type_cit_helper(obj, gdk_x11_window_get_type());
}
using f_gdk_window_get_display = GdkDisplay*(*)(GdkWindow *window);
f_gdk_window_get_display gdk_window_get_display = nullptr;
@@ -70,11 +62,6 @@ f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr;
using f_gdk_wayland_window_get_type = GType (*)(void);
f_gdk_wayland_window_get_type gdk_wayland_window_get_type = nullptr;
template <typename Object>
inline bool gdk_is_wayland_window_check(Object *obj) {
return g_type_cit_helper(obj, gdk_wayland_window_get_type());
}
using f_gdk_wayland_window_set_transient_for_exported = gboolean(*)(GdkWindow *window, char *parent_handle_str);
f_gdk_wayland_window_set_transient_for_exported gdk_wayland_window_set_transient_for_exported = nullptr;
#endif // !DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
@@ -115,7 +102,7 @@ void GdkSetTransientFor(GdkWindow *window, QWindow *parent) {
#ifndef DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
if (gdk_wayland_window_get_type != nullptr
&& gdk_wayland_window_set_transient_for_exported != nullptr
&& gdk_is_wayland_window_check(window)) {
&& GDK_IS_WAYLAND_WINDOW(window)) {
if (const auto integration = WaylandIntegration::Instance()) {
if (const auto handle = integration->nativeHandle(parent)
; !handle.isEmpty()) {
@@ -134,7 +121,7 @@ void GdkSetTransientFor(GdkWindow *window, QWindow *parent) {
&& gdk_x11_display_get_xdisplay != nullptr
&& gdk_x11_window_get_xid != nullptr
&& gdk_window_get_display != nullptr
&& gdk_is_x11_window_check(window)) {
&& GDK_IS_X11_WINDOW(window)) {
XSetTransientForHint(
gdk_x11_display_get_xdisplay(gdk_window_get_display(window)),
gdk_x11_window_get_xid(window),

View File

@@ -22,10 +22,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Platform {
namespace FileDialog {
namespace Gtk {
namespace {
using namespace Platform::Gtk;
namespace {
using Type = ::FileDialog::internal::Type;
// GTK file chooser image preview: thanks to Chromium
@@ -135,13 +135,11 @@ public:
protected:
static void onResponse(QGtkDialog *dialog, int response);
static void onUpdatePreview(QGtkDialog *dialog);
private:
void onParentWindowDestroyed();
GtkWidget *gtkWidget = nullptr;
GtkWidget *_preview = nullptr;
rpl::event_stream<> _accept;
rpl::event_stream<> _reject;
@@ -192,6 +190,7 @@ public:
private:
static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper);
static void onCurrentFolderChanged(GtkFileDialog *helper);
static void onUpdatePreview(GtkDialog *gtkDialog, GtkFileDialog *helper);
void applyOptions();
void setNameFilters(const QStringList &filters);
@@ -215,6 +214,7 @@ private:
QHash<QString, GtkFileFilter*> _filters;
QHash<GtkFileFilter*, QString> _filterNames;
QScopedPointer<QGtkDialog> d;
GtkWidget *_preview = nullptr;
rpl::lifetime _lifetime;
};
@@ -222,11 +222,6 @@ private:
QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) {
g_signal_connect_swapped(G_OBJECT(gtkWidget), "response", G_CALLBACK(onResponse), this);
g_signal_connect(G_OBJECT(gtkWidget), "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), nullptr);
if (PreviewSupported()) {
_preview = gtk_image_new();
g_signal_connect_swapped(G_OBJECT(gtkWidget), "update-preview", G_CALLBACK(onUpdatePreview), this);
gtk_file_chooser_set_preview_widget(gtk_file_chooser_cast(gtkWidget), _preview);
}
}
QGtkDialog::~QGtkDialog() {
@@ -235,7 +230,7 @@ QGtkDialog::~QGtkDialog() {
}
GtkDialog *QGtkDialog::gtkDialog() const {
return gtk_dialog_cast(gtkWidget);
return GTK_DIALOG(gtkWidget);
}
void QGtkDialog::exec() {
@@ -304,32 +299,6 @@ void QGtkDialog::onResponse(QGtkDialog *dialog, int response) {
dialog->_reject.fire({});
}
void QGtkDialog::onUpdatePreview(QGtkDialog* dialog) {
auto filename = gtk_file_chooser_get_preview_filename(gtk_file_chooser_cast(dialog->gtkWidget));
if (!filename) {
gtk_file_chooser_set_preview_widget_active(gtk_file_chooser_cast(dialog->gtkWidget), false);
return;
}
// Don't attempt to open anything which isn't a regular file. If a named pipe,
// this may hang. See https://crbug.com/534754.
struct stat stat_buf;
if (stat(filename, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)) {
g_free(filename);
gtk_file_chooser_set_preview_widget_active(gtk_file_chooser_cast(dialog->gtkWidget), false);
return;
}
// This will preserve the image's aspect ratio.
auto pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, kPreviewHeight, nullptr);
g_free(filename);
if (pixbuf) {
gtk_image_set_from_pixbuf(gtk_image_cast(dialog->_preview), pixbuf);
g_object_unref(pixbuf);
}
gtk_file_chooser_set_preview_widget_active(gtk_file_chooser_cast(dialog->gtkWidget), pixbuf ? true : false);
}
void QGtkDialog::onParentWindowDestroyed() {
// The Gtk*DialogHelper classes own this object. Make sure the parent doesn't delete it.
setParent(nullptr);
@@ -360,8 +329,14 @@ GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QStr
onRejected();
}, _lifetime);
g_signal_connect(gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
g_signal_connect_swapped(gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
g_signal_connect(GTK_FILE_CHOOSER(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this);
g_signal_connect_swapped(GTK_FILE_CHOOSER(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this);
if (PreviewSupported()) {
_preview = gtk_image_new();
g_signal_connect(G_OBJECT(d->gtkDialog()), "update-preview", G_CALLBACK(onUpdatePreview), this);
gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(d->gtkDialog()), _preview);
}
}
GtkFileDialog::~GtkFileDialog() {
@@ -435,7 +410,7 @@ bool GtkFileDialog::defaultNameFilterDisables() const {
void GtkFileDialog::setDirectory(const QString &directory) {
GtkDialog *gtkDialog = d->gtkDialog();
gtk_file_chooser_set_current_folder(gtk_file_chooser_cast(gtkDialog), directory.toUtf8().constData());
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), directory.toUtf8().constData());
}
QDir GtkFileDialog::directory() const {
@@ -446,7 +421,7 @@ QDir GtkFileDialog::directory() const {
QString ret;
GtkDialog *gtkDialog = d->gtkDialog();
gchar *folder = gtk_file_chooser_get_current_folder(gtk_file_chooser_cast(gtkDialog));
gchar *folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(gtkDialog));
if (folder) {
ret = QString::fromUtf8(folder);
g_free(folder);
@@ -467,7 +442,7 @@ QStringList GtkFileDialog::selectedFiles() const {
QStringList selection;
GtkDialog *gtkDialog = d->gtkDialog();
GSList *filenames = gtk_file_chooser_get_filenames(gtk_file_chooser_cast(gtkDialog));
GSList *filenames = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(gtkDialog));
for (GSList *it = filenames; it; it = it->next)
selection += QString::fromUtf8((const char*)it->data);
g_slist_free(filenames);
@@ -482,13 +457,13 @@ void GtkFileDialog::selectNameFilter(const QString &filter) {
GtkFileFilter *gtkFilter = _filters.value(filter);
if (gtkFilter) {
GtkDialog *gtkDialog = d->gtkDialog();
gtk_file_chooser_set_filter(gtk_file_chooser_cast(gtkDialog), gtkFilter);
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
}
}
QString GtkFileDialog::selectedNameFilter() const {
GtkDialog *gtkDialog = d->gtkDialog();
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter(gtk_file_chooser_cast(gtkDialog));
GtkFileFilter *gtkFilter = gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(gtkDialog));
return _filterNames.value(gtkFilter);
}
@@ -525,6 +500,32 @@ void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) {
// emit dialog->directoryEntered(dialog->directory());
}
void GtkFileDialog::onUpdatePreview(GtkDialog *gtkDialog, GtkFileDialog *helper) {
auto filename = gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(gtkDialog));
if (!filename) {
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
return;
}
// Don't attempt to open anything which isn't a regular file. If a named pipe,
// this may hang. See https://crbug.com/534754.
struct stat stat_buf;
if (stat(filename, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)) {
g_free(filename);
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), false);
return;
}
// This will preserve the image's aspect ratio.
auto pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, kPreviewHeight, nullptr);
g_free(filename);
if (pixbuf) {
gtk_image_set_from_pixbuf(GTK_IMAGE(helper->_preview), pixbuf);
g_object_unref(pixbuf);
}
gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(gtkDialog), pixbuf ? true : false);
}
GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) {
switch (fileMode) {
case QFileDialog::AnyFile:
@@ -546,17 +547,17 @@ GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileD
void GtkFileDialog::applyOptions() {
GtkDialog *gtkDialog = d->gtkDialog();
gtk_window_set_title(gtk_window_cast(gtkDialog), _windowTitle.toUtf8().constData());
gtk_file_chooser_set_local_only(gtk_file_chooser_cast(gtkDialog), true);
gtk_window_set_title(GTK_WINDOW(gtkDialog), _windowTitle.toUtf8().constData());
gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(gtkDialog), true);
const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode);
gtk_file_chooser_set_action(gtk_file_chooser_cast(gtkDialog), action);
gtk_file_chooser_set_action(GTK_FILE_CHOOSER(gtkDialog), action);
const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles);
gtk_file_chooser_set_select_multiple(gtk_file_chooser_cast(gtkDialog), selectMultiple);
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(gtkDialog), selectMultiple);
const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite);
gtk_file_chooser_set_do_overwrite_confirmation(gtk_file_chooser_cast(gtkDialog), confirmOverwrite);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(gtkDialog), confirmOverwrite);
if (!_nameFilters.isEmpty())
setNameFilters(_nameFilters);
@@ -567,12 +568,12 @@ void GtkFileDialog::applyOptions() {
for_const (const auto &filename, _initialFiles) {
if (_acceptMode == QFileDialog::AcceptSave) {
QFileInfo fi(filename);
gtk_file_chooser_set_current_folder(gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8().constData());
gtk_file_chooser_set_current_name(gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8().constData());
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), fi.path().toUtf8().constData());
gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(gtkDialog), fi.fileName().toUtf8().constData());
} else if (filename.endsWith('/')) {
gtk_file_chooser_set_current_folder(gtk_file_chooser_cast(gtkDialog), filename.toUtf8().constData());
gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(gtkDialog), filename.toUtf8().constData());
} else {
gtk_file_chooser_select_filename(gtk_file_chooser_cast(gtkDialog), filename.toUtf8().constData());
gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(gtkDialog), filename.toUtf8().constData());
}
}
@@ -584,19 +585,19 @@ void GtkFileDialog::applyOptions() {
GtkWidget *acceptButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK);
if (acceptButton) {
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept))
gtk_button_set_label(gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8().constData());
gtk_button_set_label(GTK_BUTTON(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8().constData());
else*/ if (_acceptMode == QFileDialog::AcceptOpen)
gtk_button_set_label(gtk_button_cast(acceptButton), tr::lng_open_link(tr::now).toUtf8().constData());
gtk_button_set_label(GTK_BUTTON(acceptButton), tr::lng_open_link(tr::now).toUtf8().constData());
else
gtk_button_set_label(gtk_button_cast(acceptButton), tr::lng_settings_save(tr::now).toUtf8().constData());
gtk_button_set_label(GTK_BUTTON(acceptButton), tr::lng_settings_save(tr::now).toUtf8().constData());
}
GtkWidget *rejectButton = gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL);
if (rejectButton) {
/*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject))
gtk_button_set_label(gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8().constData());
gtk_button_set_label(GTK_BUTTON(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8().constData());
else*/
gtk_button_set_label(gtk_button_cast(rejectButton), tr::lng_cancel(tr::now).toUtf8().constData());
gtk_button_set_label(GTK_BUTTON(rejectButton), tr::lng_cancel(tr::now).toUtf8().constData());
}
}
}
@@ -604,7 +605,7 @@ void GtkFileDialog::applyOptions() {
void GtkFileDialog::setNameFilters(const QStringList &filters) {
GtkDialog *gtkDialog = d->gtkDialog();
Q_FOREACH (GtkFileFilter *filter, _filters)
gtk_file_chooser_remove_filter(gtk_file_chooser_cast(gtkDialog), filter);
gtk_file_chooser_remove_filter(GTK_FILE_CHOOSER(gtkDialog), filter);
_filters.clear();
_filterNames.clear();
@@ -631,7 +632,7 @@ void GtkFileDialog::setNameFilters(const QStringList &filters) {
gtk_file_filter_add_pattern(gtkFilter, caseInsensitiveExt.toUtf8().constData());
}
gtk_file_chooser_add_filter(gtk_file_chooser_cast(gtkDialog), gtkFilter);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(gtkDialog), gtkFilter);
_filters.insert(filter, gtkFilter);
_filterNames.insert(gtkFilter, filter);
@@ -640,16 +641,7 @@ void GtkFileDialog::setNameFilters(const QStringList &filters) {
} // namespace
bool Use(Type type) {
if (!Supported()) {
return false;
}
return qEnvironmentVariableIsSet("TDESKTOP_USE_GTK_FILE_DIALOG")
|| DesktopEnvironment::IsGtkBased();
}
bool Get(
std::optional<bool> Get(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
@@ -657,6 +649,12 @@ bool Get(
const QString &filter,
Type type,
QString startFile) {
if (!Supported()
|| (!qEnvironmentVariableIsSet("TDESKTOP_USE_GTK_FILE_DIALOG")
&& !DesktopEnvironment::IsGtkBased())) {
return std::nullopt;
}
if (cDialogLastPath().isEmpty()) {
InitLastPath();
}

View File

@@ -13,16 +13,13 @@ namespace Platform {
namespace FileDialog {
namespace Gtk {
using Type = ::FileDialog::internal::Type;
bool Use(Type type = Type::ReadFile);
bool Get(
std::optional<bool> Get(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
Type type,
::FileDialog::internal::Type type,
QString startFile);
} // namespace Gtk

View File

@@ -158,17 +158,13 @@ std::optional<int> GtkIntegration::scaleFactor() const {
return gdk_monitor_get_scale_factor(monitor);
}
bool GtkIntegration::useFileDialog(FileDialogType type) const {
return FileDialog::Gtk::Use(type);
}
bool GtkIntegration::getFileDialog(
std::optional<bool> GtkIntegration::getFileDialog(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
FileDialogType type,
::FileDialog::internal::Type type,
QString startFile) const {
return FileDialog::Gtk::Get(
parent,

View File

@@ -20,16 +20,13 @@ public:
[[nodiscard]] std::optional<int> scaleFactor() const;
using FileDialogType = ::FileDialog::internal::Type;
[[nodiscard]] bool useFileDialog(
FileDialogType type = FileDialogType::ReadFile) const;
[[nodiscard]] bool getFileDialog(
[[nodiscard]] std::optional<bool> getFileDialog(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
FileDialogType type,
::FileDialog::internal::Type type,
QString startFile) const;
[[nodiscard]] bool showOpenWithDialog(const QString &filepath) const;

View File

@@ -24,19 +24,15 @@ std::optional<int> GtkIntegration::scaleFactor() const {
return std::nullopt;
}
bool GtkIntegration::useFileDialog(FileDialogType type) const {
return false;
}
bool GtkIntegration::getFileDialog(
std::optional<bool> GtkIntegration::getFileDialog(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
FileDialogType type,
::FileDialog::internal::Type type,
QString startFile) const {
return false;
return std::nullopt;
}
bool GtkIntegration::showOpenWithDialog(const QString &filepath) const {

View File

@@ -12,10 +12,6 @@ extern "C" {
#include <gdk/gdk.h>
} // extern "C"
// To be able to compile with gtk-2.0 headers as well
typedef struct _GdkMonitor GdkMonitor;
typedef struct _GtkAppChooser GtkAppChooser;
namespace Platform {
namespace Gtk {
@@ -31,6 +27,7 @@ inline GtkSelectionData* (*gtk_clipboard_wait_for_contents)(GtkClipboard *clipbo
inline GdkPixbuf* (*gtk_clipboard_wait_for_image)(GtkClipboard *clipboard) = nullptr;
inline gboolean (*gtk_selection_data_targets_include_image)(const GtkSelectionData *selection_data, gboolean writable) = nullptr;
inline void (*gtk_selection_data_free)(GtkSelectionData *data) = nullptr;
inline GType (*gtk_file_chooser_get_type)(void) G_GNUC_CONST = nullptr;
inline GtkWidget* (*gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED = nullptr;
inline gboolean (*gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename) = nullptr;
inline gchar* (*gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser) = nullptr;
@@ -39,12 +36,15 @@ inline gboolean (*gtk_file_chooser_select_filename)(GtkFileChooser *chooser, con
inline GSList* (*gtk_file_chooser_get_filenames)(GtkFileChooser *chooser) = nullptr;
inline void (*gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter) = nullptr;
inline GtkFileFilter* (*gtk_file_chooser_get_filter)(GtkFileChooser *chooser) = nullptr;
inline GType (*gtk_window_get_type)(void) G_GNUC_CONST = nullptr;
inline void (*gtk_window_set_title)(GtkWindow *window, const gchar *title) = nullptr;
inline void (*gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only) = nullptr;
inline void (*gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action) = nullptr;
inline void (*gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple) = nullptr;
inline void (*gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation) = nullptr;
inline GType (*gtk_dialog_get_type)(void) G_GNUC_CONST = nullptr;
inline GtkWidget* (*gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id) = nullptr;
inline GType (*gtk_button_get_type)(void) G_GNUC_CONST = nullptr;
inline void (*gtk_button_set_label)(GtkButton *button, const gchar *label) = nullptr;
inline void (*gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter) = nullptr;
inline void (*gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name) = nullptr;
@@ -54,65 +54,14 @@ inline void (*gtk_file_chooser_set_preview_widget)(GtkFileChooser *chooser, GtkW
inline gchar* (*gtk_file_chooser_get_preview_filename)(GtkFileChooser *chooser) = nullptr;
inline void (*gtk_file_chooser_set_preview_widget_active)(GtkFileChooser *chooser, gboolean active) = nullptr;
inline GtkFileFilter* (*gtk_file_filter_new)(void) = nullptr;
inline GType (*gtk_image_get_type)(void) G_GNUC_CONST = nullptr;
inline GtkWidget* (*gtk_image_new)(void) = nullptr;
inline void (*gtk_image_set_from_pixbuf)(GtkImage *image, GdkPixbuf *pixbuf) = nullptr;
inline GType (*gtk_app_chooser_get_type)(void) G_GNUC_CONST = nullptr;
inline GtkWidget* (*gtk_app_chooser_dialog_new)(GtkWindow *parent, GtkDialogFlags flags, GFile *file) = nullptr;
inline GAppInfo* (*gtk_app_chooser_get_app_info)(GtkAppChooser *self) = nullptr;
inline void (*gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal) = nullptr;
inline void (*gdk_window_focus)(GdkWindow *window, guint32 timestamp) = nullptr;
template <typename Result, typename Object>
inline Result *g_type_cic_helper(Object *instance, GType iface_type) {
return reinterpret_cast<Result*>(g_type_check_instance_cast(reinterpret_cast<GTypeInstance*>(instance), iface_type));
}
inline GType (*gtk_dialog_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkDialog *gtk_dialog_cast(Object *obj) {
return g_type_cic_helper<GtkDialog, Object>(obj, gtk_dialog_get_type());
}
inline GType (*gtk_file_chooser_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) {
return g_type_cic_helper<GtkFileChooser, Object>(obj, gtk_file_chooser_get_type());
}
inline GType (*gtk_image_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkImage *gtk_image_cast(Object *obj) {
return g_type_cic_helper<GtkImage, Object>(obj, gtk_image_get_type());
}
inline GType (*gtk_button_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkButton *gtk_button_cast(Object *obj) {
return g_type_cic_helper<GtkButton, Object>(obj, gtk_button_get_type());
}
inline GType (*gtk_window_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkWindow *gtk_window_cast(Object *obj) {
return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type());
}
inline GType (*gtk_app_chooser_get_type)(void) G_GNUC_CONST = nullptr;
template <typename Object>
inline GtkAppChooser *gtk_app_chooser_cast(Object *obj) {
return g_type_cic_helper<GtkAppChooser, Object>(obj, gtk_app_chooser_get_type());
}
template <typename Object>
inline bool g_type_cit_helper(Object *instance, GType iface_type) {
if (!instance) return false;
auto ginstance = reinterpret_cast<GTypeInstance*>(instance);
if (ginstance->g_class && ginstance->g_class->g_type == iface_type) {
return true;
}
return g_type_check_instance_is_a(ginstance, iface_type);
}
inline gint (*gtk_dialog_run)(GtkDialog *dialog) = nullptr;
inline GdkAtom (*gdk_atom_intern)(const gchar *atom_name, gboolean only_if_exists) = nullptr;
inline GdkDisplay* (*gdk_display_get_default)(void) = nullptr;

View File

@@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include <private/qguiapplication_p.h>
#include <giomm.h>
namespace Platform {
namespace File {
@@ -21,6 +22,12 @@ namespace {
using namespace Platform::Gtk;
struct GtkWidgetDeleter {
void operator()(GtkWidget *widget) {
gtk_widget_destroy(widget);
}
};
bool Supported() {
return (gtk_app_chooser_dialog_new != nullptr)
&& (gtk_app_chooser_get_app_info != nullptr)
@@ -34,48 +41,42 @@ bool Supported() {
class GtkOpenWithDialog : public QWindow {
public:
GtkOpenWithDialog(const QString &filepath);
~GtkOpenWithDialog();
bool exec();
private:
static void handleResponse(GtkOpenWithDialog *dialog, int responseId);
GFile *_gfileInstance = nullptr;
GtkWidget *_gtkWidget = nullptr;
const Glib::RefPtr<Gio::File> _file;
const std::unique_ptr<GtkWidget, GtkWidgetDeleter> _gtkWidget;
QEventLoop _loop;
std::optional<bool> _result;
};
GtkOpenWithDialog::GtkOpenWithDialog(const QString &filepath)
: _gfileInstance(g_file_new_for_path(filepath.toUtf8().constData()))
: _file(Gio::File::create_for_path(filepath.toStdString()))
, _gtkWidget(gtk_app_chooser_dialog_new(
nullptr,
GTK_DIALOG_MODAL,
_gfileInstance)) {
_file->gobj())) {
g_signal_connect_swapped(
_gtkWidget,
_gtkWidget.get(),
"response",
G_CALLBACK(handleResponse),
this);
}
GtkOpenWithDialog::~GtkOpenWithDialog() {
gtk_widget_destroy(_gtkWidget);
g_object_unref(_gfileInstance);
}
bool GtkOpenWithDialog::exec() {
gtk_widget_realize(_gtkWidget);
gtk_widget_realize(_gtkWidget.get());
if (const auto activeWindow = Core::App().activeWindow()) {
Platform::internal::GdkSetTransientFor(
gtk_widget_get_window(_gtkWidget),
gtk_widget_get_window(_gtkWidget.get()),
activeWindow->widget()->windowHandle());
}
QGuiApplicationPrivate::showModalWindow(this);
gtk_widget_show(_gtkWidget);
gtk_widget_show(_gtkWidget.get());
if (!_result.has_value()) {
_loop.exec();
@@ -86,20 +87,20 @@ bool GtkOpenWithDialog::exec() {
}
void GtkOpenWithDialog::handleResponse(GtkOpenWithDialog *dialog, int responseId) {
GAppInfo *chosenAppInfo = nullptr;
Glib::RefPtr<Gio::AppInfo> chosenAppInfo;
dialog->_result = true;
switch (responseId) {
case GTK_RESPONSE_OK:
chosenAppInfo = gtk_app_chooser_get_app_info(
gtk_app_chooser_cast(dialog->_gtkWidget));
chosenAppInfo = Glib::wrap(gtk_app_chooser_get_app_info(
GTK_APP_CHOOSER(dialog->_gtkWidget.get())));
if (chosenAppInfo) {
GList *uris = nullptr;
uris = g_list_prepend(uris, g_file_get_uri(dialog->_gfileInstance));
g_app_info_launch_uris(chosenAppInfo, uris, nullptr, nullptr);
g_list_free(uris);
g_object_unref(chosenAppInfo);
try {
chosenAppInfo->launch_uri(dialog->_file->get_uri());
} catch (...) {
}
chosenAppInfo = {};
}
break;

View File

@@ -28,6 +28,8 @@ namespace FileDialog {
namespace XDP {
namespace {
using Type = ::FileDialog::internal::Type;
constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
constexpr auto kXDGDesktopPortalFileChooserInterface = "org.freedesktop.portal.FileChooser"_cs;
@@ -703,11 +705,6 @@ void Start() {
ComputeFileChooserPortalVersion();
}
bool Use(Type type) {
return FileChooserPortalVersion.has_value()
&& (type != Type::ReadFolder || *FileChooserPortalVersion >= 3);
}
std::optional<bool> Get(
QPointer<QWidget> parent,
QStringList &files,
@@ -716,6 +713,11 @@ std::optional<bool> Get(
const QString &filter,
Type type,
QString startFile) {
if (!FileChooserPortalVersion.has_value()
|| (type == Type::ReadFolder && *FileChooserPortalVersion < 3)) {
return std::nullopt;
}
static const auto docRegExp = QRegularExpression("^/run/user/\\d+/doc");
if (cDialogLastPath().isEmpty()
|| cDialogLastPath().contains(docRegExp)) {

View File

@@ -13,17 +13,14 @@ namespace Platform {
namespace FileDialog {
namespace XDP {
using Type = ::FileDialog::internal::Type;
void Start();
bool Use(Type type = Type::ReadFile);
std::optional<bool> Get(
QPointer<QWidget> parent,
QStringList &files,
QByteArray &remoteContent,
const QString &caption,
const QString &filter,
Type type,
::FileDialog::internal::Type type,
QString startFile);
} // namespace XDP

View File

@@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtGui/QWindow>
#include <fcntl.h>
#include <gio/gunixfdlist.h>
#include <glibmm.h>
#include <giomm.h>
#include <private/qguiapplication_p.h>
@@ -79,7 +78,6 @@ bool XDPOpenWithDialog::exec() {
}
const auto fdGuard = gsl::finally([&] { ::close(fd); });
auto outFdList = Glib::RefPtr<Gio::UnixFDList>();
const auto parentWindowId = [&]() -> Glib::ustring {
std::stringstream result;
@@ -138,6 +136,10 @@ bool XDPOpenWithDialog::exec() {
}
});
const auto fdList = Gio::UnixFDList::create();
fdList->append(fd);
auto outFdList = Glib::RefPtr<Gio::UnixFDList>();
connection->call_sync(
std::string(kXDGDesktopPortalObjectPath),
std::string(kXDGDesktopPortalOpenURIInterface),
@@ -159,7 +161,7 @@ bool XDPOpenWithDialog::exec() {
},
}),
}),
Glib::wrap(g_unix_fd_list_new_from_array(&fd, 1)),
fdList,
outFdList,
std::string(kXDGDesktopPortalService));

View File

@@ -260,8 +260,17 @@ void MediaSlider::paintEvent(QPaintEvent *e) {
: seekRect.height();
const auto from = 0;
const auto length = (horizontal ? width() : height());
const auto mid = qRound(from + value * length);
const auto till = std::max(mid, qRound(from + receivedTill * length));
const auto alwaysSeekSize = horizontal
? _st.seekSize.width()
: _st.seekSize.height();
const auto mid = _alwaysDisplayMarker
? qRound(from
+ (alwaysSeekSize / 2.)
+ value * (length - alwaysSeekSize))
: qRound(from + value * length);
const auto till = horizontal
? std::max(mid, qRound(from + receivedTill * length))
: mid;
const auto end = from + length;
const auto activeFg = disabled
? _st.activeFgDisabled

View File

@@ -76,7 +76,7 @@ Manager::Manager(System *system)
system->settingsChanged(
) | rpl::start_with_next([=](ChangeType change) {
settingsChanged(change);
}, system->lifetime());
}, _lifetime);
}
Manager::QueuedNotification::QueuedNotification(

View File

@@ -126,6 +126,8 @@ private:
mutable QPixmap _hiddenUserpicPlaceholder;
rpl::lifetime _lifetime;
};
namespace internal {

View File

@@ -25,13 +25,20 @@ void Adaptive::setChatLayout(ChatLayout value) {
_chatLayout = value;
}
rpl::producer<> Adaptive::changed() const {
rpl::producer<> Adaptive::value() const {
return rpl::merge(
Core::App().settings().adaptiveForWideValue() | rpl::to_empty,
_chatLayout.changes() | rpl::to_empty,
_layout.changes() | rpl::to_empty);
}
rpl::producer<> Adaptive::changes() const {
return rpl::merge(
Core::App().settings().adaptiveForWideChanges() | rpl::to_empty,
_chatLayout.changes() | rpl::to_empty,
_layout.changes() | rpl::to_empty);
}
rpl::producer<bool> Adaptive::oneColumnValue() const {
return _layout.value(
) | rpl::map([=] {

View File

@@ -27,7 +27,8 @@ public:
void setWindowLayout(WindowLayout value);
void setChatLayout(ChatLayout value);
[[nodiscard]] rpl::producer<> changed() const;
[[nodiscard]] rpl::producer<> value() const;
[[nodiscard]] rpl::producer<> changes() const;
[[nodiscard]] rpl::producer<bool> oneColumnValue() const;
[[nodiscard]] rpl::producer<ChatLayout> chatLayoutValue() const;

View File

@@ -21,7 +21,7 @@ struct OpenRequest;
namespace Window {
class Controller final {
class Controller final : public base::has_weak_ptr {
public:
Controller();
~Controller();

View File

@@ -507,18 +507,18 @@ void Filler::addUserActions(not_null<UserData*> user) {
}
void Filler::addChatActions(not_null<ChatData*> chat) {
const auto navigation = _controller;
if (_request.section != Section::ChatsList) {
const auto controller = _controller;
if (EditPeerInfoBox::Available(chat)) {
const auto text = tr::lng_manage_group_title(tr::now);
_addAction(text, [=] {
controller->showEditPeerBox(chat);
navigation->showEditPeerBox(chat);
});
}
if (chat->canAddMembers()) {
_addAction(
tr::lng_channel_add_members(tr::now),
[=] { AddChatMembers(controller, chat); });
[=] { AddChatMembers(navigation, chat); });
}
addPollAction(chat);
if (chat->canExportChatHistory()) {
@@ -533,6 +533,13 @@ void Filler::addChatActions(not_null<ChatData*> chat) {
_addAction(
tr::lng_profile_clear_history(tr::now),
ClearHistoryHandler(_peer));
if (_request.section != Section::ChatsList) {
if (!chat->amCreator()) {
_addAction(tr::lng_profile_report(tr::now), [=] {
HistoryView::ShowReportPeerBox(navigation, chat);
});
}
}
}
void Filler::addChannelActions(not_null<ChannelData*> channel) {
@@ -597,9 +604,7 @@ void Filler::addChannelActions(not_null<ChannelData*> channel) {
[=] { channel->session().api().joinChannel(channel); });
}
if (_request.section != Section::ChatsList) {
const auto needReport = !channel->amCreator()
&& (!isGroup || channel->isPublic());
if (needReport) {
if (!channel->amCreator()) {
_addAction(tr::lng_profile_report(tr::now), [=] {
HistoryView::ShowReportPeerBox(navigation, channel);
});

View File

@@ -1,7 +1,7 @@
AppVersion 2007010
AppVersionStrMajor 2.7
AppVersionStrSmall 2.7.10
AppVersionStr 2.7.10
BetaChannel 1
AppVersion 2008002
AppVersionStrMajor 2.8
AppVersionStrSmall 2.8.2
AppVersionStr 2.8.2
BetaChannel 0
AlphaVersion 0
AppVersionOriginal 2.7.10.beta
AppVersionOriginal 2.8.2

View File

@@ -1,3 +1,19 @@
2.8.2 (27.06.21)
- Attempt to fix random crashes on macOS.
2.8.1 (26.06.21)
- Fix crash in audio player volume slider.
2.8 (24.06.21)
- Start video conferences from Voice Chats in any group.
- Share your screen or video from your camera with up to 30 participants (limit to be increased soon).
- Talk without video with an unlimited number of participants.
- Create voice chats from the info page of any group where you are an admin.
- Group video calls are supported natively on all devices, including iPads and laptops.
2.7.10 beta (22.06.21)
- Added ability to mix together bold, italic and other formatting.

2
cmake

Submodule cmake updated: c29450cbf1...1d59503a24

View File

@@ -34,7 +34,7 @@ Open **x64 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
cd ThirdParty
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout 41ead72
git checkout 7f8a282
cd ../
git clone https://chromium.googlesource.com/external/gyp
cd gyp
@@ -65,7 +65,7 @@ Open **x64 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout 41ead72
git checkout 7f8a282
cd ..
git clone https://github.com/desktop-app/lzma.git

View File

@@ -34,7 +34,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
cd ThirdParty
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout ad34925
git checkout 7f8a282
cd ../
git clone https://chromium.googlesource.com/external/gyp
cd gyp
@@ -65,7 +65,7 @@ Open **x86 Native Tools Command Prompt for VS 2019.bat**, go to ***BuildPath***
git clone https://github.com/desktop-app/patches.git
cd patches
git checkout ad34925
git checkout 7f8a282
cd ..
git clone https://github.com/desktop-app/lzma.git

View File

@@ -92,8 +92,8 @@ Go to ***BuildPath*** and run
git clone https://github.com/openssl/openssl openssl_1_1_1
cd openssl_1_1_1
git checkout OpenSSL_1_1_1-stable
./Configure --prefix=/usr/local/macos no-tests darwin64-x86_64-cc -static $MIN_VER
git checkout OpenSSL_1_1_1k
./Configure --prefix=/usr/local/macos no-tests darwin64-x86_64-cc -static -g3 $MIN_VER
make build_libs $MAKE_THREADS_CNT
cd ..
@@ -268,8 +268,8 @@ Go to ***BuildPath*** and run
cd ../../..
build/gyp_crashpad.py -Dmac_deployment_target=10.10
ninja -C out/Debug
ninja -C out/Release
ninja -C out/Debug base crashpad_util crashpad_client crashpad_handler
ninja -C out/Release base crashpad_util crashpad_client crashpad_handler
cd ..
git clone git://code.qt.io/qt/qt5.git qt_5_15_2