Compare commits
25 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1704cb345a | ||
|
|
0b85d0f185 | ||
|
|
348dfefbaa | ||
|
|
7508980f62 | ||
|
|
e11efe483e | ||
|
|
b23e4fa491 | ||
|
|
b6b7f5706f | ||
|
|
613bf98283 | ||
|
|
0bdb38753b | ||
|
|
d557e0f2b7 | ||
|
|
e81f4e8545 | ||
|
|
3b7d5d3c80 | ||
|
|
0c37990ccd | ||
|
|
0fbea454bc | ||
|
|
d4d688d494 | ||
|
|
b3892f49fa | ||
|
|
daa3a2f62f | ||
|
|
5affb168a2 | ||
|
|
99af2a7058 | ||
|
|
b9acea9cef | ||
|
|
8fb6ece796 | ||
|
|
15a9842b9f | ||
|
|
b28da30038 | ||
|
|
8ce0bd5575 | ||
|
|
5d68d224e5 |
4
.github/workflows/mac.yml
vendored
4
.github/workflows/mac.yml
vendored
@@ -102,6 +102,8 @@ jobs:
|
||||
cd Libraries/macos
|
||||
echo "LibrariesPath=`pwd`" >> $GITHUB_ENV
|
||||
|
||||
curl -o tg_owt-version.json https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master
|
||||
|
||||
- name: Patches.
|
||||
run: |
|
||||
echo "Find necessary commit from doc."
|
||||
@@ -475,7 +477,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/tg_owt
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_owt-version.json') }}
|
||||
- name: WebRTC.
|
||||
if: steps.cache-webrtc.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
|
||||
3
.github/workflows/win.yml
vendored
3
.github/workflows/win.yml
vendored
@@ -103,6 +103,7 @@ jobs:
|
||||
- name: Generate cache key.
|
||||
shell: bash
|
||||
run: |
|
||||
curl -o $LibrariesPath/tg_owt-version.json https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master
|
||||
echo $MANUAL_CACHING >> CACHE_KEY.txt
|
||||
if [ "$AUTO_CACHING" == "1" ]; then
|
||||
thisFile=$REPO_NAME/.github/workflows/win.yml
|
||||
@@ -359,7 +360,7 @@ jobs:
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.LibrariesPath }}/tg_owt
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}
|
||||
key: ${{ runner.OS }}-webrtc-${{ env.CACHE_KEY }}-${{ hashFiles('**/tg_owt-version.json') }}
|
||||
- name: WebRTC.
|
||||
if: steps.cache-webrtc.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
|
||||
2
LEGAL
2
LEGAL
@@ -1,7 +1,7 @@
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
Copyright (c) 2014-2020 The Telegram Desktop Authors.
|
||||
Copyright (c) 2014-2021 The Telegram Desktop Authors.
|
||||
|
||||
Telegram Desktop is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -84,6 +84,13 @@ if (LINUX)
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION)
|
||||
target_link_libraries(Telegram
|
||||
PRIVATE
|
||||
desktop-app::external_kwayland
|
||||
)
|
||||
endif()
|
||||
|
||||
if (DESKTOP_APP_USE_PACKAGED
|
||||
AND NOT DESKTOP_APP_DISABLE_WAYLAND_INTEGRATION
|
||||
AND Qt5WaylandClient_VERSION VERSION_LESS 5.13.0)
|
||||
@@ -1107,6 +1114,12 @@ if (LINUX AND DESKTOP_APP_DISABLE_DBUS_INTEGRATION)
|
||||
remove_target_sources(Telegram ${src_loc}
|
||||
platform/linux/linux_gsd_media_keys.cpp
|
||||
platform/linux/linux_gsd_media_keys.h
|
||||
platform/linux/notifications_manager_linux.cpp
|
||||
)
|
||||
|
||||
nice_target_sources(Telegram ${src_loc}
|
||||
PRIVATE
|
||||
platform/linux/notifications_manager_linux_dummy.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Identity Name="TelegramMessengerLLP.TelegramDesktop"
|
||||
ProcessorArchitecture="ARCHITECTURE"
|
||||
Publisher="CN=536BC709-8EE1-4478-AF22-F0F0F26FF64A"
|
||||
Version="2.5.3.0" />
|
||||
Version="2.5.4.0" />
|
||||
<Properties>
|
||||
<DisplayName>Telegram Desktop</DisplayName>
|
||||
<PublisherDisplayName>Telegram FZ-LLC</PublisherDisplayName>
|
||||
|
||||
@@ -44,8 +44,8 @@ IDI_ICON1 ICON "..\\art\\icon256.ico"
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,5,3,0
|
||||
PRODUCTVERSION 2,5,3,0
|
||||
FILEVERSION 2,5,4,0
|
||||
PRODUCTVERSION 2,5,4,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.5.3.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "FileVersion", "2.5.4.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.5.3.0"
|
||||
VALUE "ProductVersion", "2.5.4.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -35,8 +35,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,5,3,0
|
||||
PRODUCTVERSION 2,5,3,0
|
||||
FILEVERSION 2,5,4,0
|
||||
PRODUCTVERSION 2,5,4,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.5.3.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2020"
|
||||
VALUE "FileVersion", "2.5.4.0"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2014-2021"
|
||||
VALUE "ProductName", "Telegram Desktop"
|
||||
VALUE "ProductVersion", "2.5.3.0"
|
||||
VALUE "ProductVersion", "2.5.4.0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
||||
@@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "calls/calls_panel.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "webrtc/webrtc_media_devices.h"
|
||||
#include "webrtc/webrtc_create_adm.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "facades.h"
|
||||
@@ -779,6 +780,8 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
|
||||
sendSignalingData(bytes);
|
||||
});
|
||||
},
|
||||
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
|
||||
settings.callAudioBackend()),
|
||||
};
|
||||
if (Logs::DebugEnabled()) {
|
||||
auto callLogFolder = cWorkingDir() + qsl("DebugLogs");
|
||||
|
||||
@@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_session.h"
|
||||
#include "base/global_shortcuts.h"
|
||||
#include "webrtc/webrtc_media_devices.h"
|
||||
#include "webrtc/webrtc_create_adm.h"
|
||||
|
||||
#include <tgcalls/group/GroupInstanceImpl.h>
|
||||
|
||||
@@ -581,6 +582,8 @@ void GroupCall::createAndStartController() {
|
||||
},
|
||||
.initialInputDeviceId = _audioInputId.toStdString(),
|
||||
.initialOutputDeviceId = _audioOutputId.toStdString(),
|
||||
.createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator(
|
||||
settings.callAudioBackend()),
|
||||
};
|
||||
if (Logs::DebugEnabled()) {
|
||||
auto callLogFolder = cWorkingDir() + qsl("DebugLogs");
|
||||
|
||||
@@ -480,6 +480,7 @@ void GroupCallSettingsBox(
|
||||
// Means we finished showing the box.
|
||||
crl::on_main(box, [=] {
|
||||
state->micTester = std::make_unique<Webrtc::AudioInputTester>(
|
||||
Core::App().settings().callAudioBackend(),
|
||||
Core::App().settings().callInputDeviceId());
|
||||
state->levelUpdateTimer.callEach(kMicTestUpdateInterval);
|
||||
});
|
||||
|
||||
@@ -89,6 +89,16 @@ std::map<int, const char*> BetaLogs() {
|
||||
|
||||
"- Fix blurred thumbnails in Shared Links section.\n"
|
||||
},
|
||||
{
|
||||
2005004,
|
||||
"- Implement new audio module code for calls and voice chats.\n"
|
||||
|
||||
"- Allow retracting votes from polls in comments to channel posts.\n"
|
||||
|
||||
"- Show small voice chat button for empty voice chats.\n"
|
||||
|
||||
"- Fix media viewer updating when screen resolution is changed.\n"
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -13,12 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/section_widget.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "webrtc/webrtc_create_adm.h"
|
||||
#include "facades.h"
|
||||
|
||||
namespace Core {
|
||||
|
||||
Settings::Settings()
|
||||
: _sendSubmitWay(Ui::InputSubmitSettings::Enter)
|
||||
: _callAudioBackend(Webrtc::Backend::OpenAL)
|
||||
, _sendSubmitWay(Ui::InputSubmitSettings::Enter)
|
||||
, _floatPlayerColumn(Window::Column::Second)
|
||||
, _floatPlayerCorner(RectPart::TopRight)
|
||||
, _dialogsWidthRatio(DefaultDialogsWidthRatio()) {
|
||||
@@ -112,7 +114,8 @@ QByteArray Settings::serialize() const {
|
||||
<< qint32(_ipRevealWarning ? 1 : 0)
|
||||
<< qint32(_groupCallPushToTalk ? 1 : 0)
|
||||
<< _groupCallPushToTalkShortcut
|
||||
<< qint64(_groupCallPushToTalkDelay);
|
||||
<< qint64(_groupCallPushToTalkDelay)
|
||||
<< qint32(_callAudioBackend);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -183,6 +186,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
qint32 groupCallPushToTalk = _groupCallPushToTalk ? 1 : 0;
|
||||
QByteArray groupCallPushToTalkShortcut = _groupCallPushToTalkShortcut;
|
||||
qint64 groupCallPushToTalkDelay = _groupCallPushToTalkDelay;
|
||||
qint32 callAudioBackend = static_cast<qint32>(_callAudioBackend);
|
||||
|
||||
stream >> themesAccentColors;
|
||||
if (!stream.atEnd()) {
|
||||
@@ -275,6 +279,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
>> groupCallPushToTalkShortcut
|
||||
>> groupCallPushToTalkDelay;
|
||||
}
|
||||
if (!stream.atEnd()) {
|
||||
stream >> callAudioBackend;
|
||||
}
|
||||
if (stream.status() != QDataStream::Ok) {
|
||||
LOG(("App Error: "
|
||||
"Bad data for Core::Settings::constructFromSerialized()"));
|
||||
@@ -369,6 +376,12 @@ void Settings::addFromSerialized(const QByteArray &serialized) {
|
||||
_groupCallPushToTalk = (groupCallPushToTalk == 1);
|
||||
_groupCallPushToTalkShortcut = groupCallPushToTalkShortcut;
|
||||
_groupCallPushToTalkDelay = groupCallPushToTalkDelay;
|
||||
auto uncheckedBackend = static_cast<Webrtc::Backend>(callAudioBackend);
|
||||
switch (uncheckedBackend) {
|
||||
case Webrtc::Backend::OpenAL:
|
||||
case Webrtc::Backend::ADM:
|
||||
case Webrtc::Backend::ADM2: _callAudioBackend = uncheckedBackend; break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Settings::chatWide() const {
|
||||
|
||||
@@ -21,6 +21,10 @@ namespace Window {
|
||||
enum class Column;
|
||||
} // namespace Window
|
||||
|
||||
namespace Webrtc {
|
||||
enum class Backend;
|
||||
} // namespace Webrtc
|
||||
|
||||
namespace Core {
|
||||
|
||||
class Settings final {
|
||||
@@ -217,6 +221,12 @@ public:
|
||||
void setCallAudioDuckingEnabled(bool value) {
|
||||
_callAudioDuckingEnabled = value;
|
||||
}
|
||||
[[nodiscard]] Webrtc::Backend callAudioBackend() const {
|
||||
return _callAudioBackend;
|
||||
}
|
||||
void setCallAudioBackend(Webrtc::Backend backend) {
|
||||
_callAudioBackend = backend;
|
||||
}
|
||||
[[nodiscard]] bool groupCallPushToTalk() const {
|
||||
return _groupCallPushToTalk;
|
||||
}
|
||||
@@ -531,13 +541,14 @@ private:
|
||||
int _callOutputVolume = 100;
|
||||
int _callInputVolume = 100;
|
||||
bool _callAudioDuckingEnabled = true;
|
||||
Webrtc::Backend _callAudioBackend = Webrtc::Backend();
|
||||
bool _groupCallPushToTalk = false;
|
||||
QByteArray _groupCallPushToTalkShortcut;
|
||||
crl::time _groupCallPushToTalkDelay = 20;
|
||||
Window::Theme::AccentColors _themesAccentColors;
|
||||
bool _lastSeenWarningSeen = false;
|
||||
Ui::SendFilesWay _sendFilesWay;
|
||||
Ui::InputSubmitSettings _sendSubmitWay;
|
||||
Ui::SendFilesWay _sendFilesWay = Ui::SendFilesWay();
|
||||
Ui::InputSubmitSettings _sendSubmitWay = Ui::InputSubmitSettings();
|
||||
base::flat_map<QString, QString> _soundOverrides;
|
||||
bool _exeLaunchWarning = true;
|
||||
bool _ipRevealWarning = true;
|
||||
@@ -553,8 +564,8 @@ private:
|
||||
rpl::variable<bool> _autoDownloadDictionaries = true;
|
||||
rpl::variable<bool> _mainMenuAccountsShown = true;
|
||||
bool _tabbedSelectorSectionEnabled = false; // per-window
|
||||
Window::Column _floatPlayerColumn; // per-window
|
||||
RectPart _floatPlayerCorner; // per-window
|
||||
Window::Column _floatPlayerColumn = Window::Column(); // per-window
|
||||
RectPart _floatPlayerCorner = RectPart(); // per-window
|
||||
bool _thirdSectionInfoEnabled = true; // per-window
|
||||
rpl::event_stream<bool> _thirdSectionInfoEnabledValue; // per-window
|
||||
int _thirdSectionExtendedBy = -1; // per-window
|
||||
|
||||
@@ -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 = 2005003;
|
||||
constexpr auto AppVersionStr = "2.5.3";
|
||||
constexpr auto AppVersion = 2005004;
|
||||
constexpr auto AppVersionStr = "2.5.4";
|
||||
constexpr auto AppBetaVersion = true;
|
||||
constexpr auto AppAlphaVersion = TDESKTOP_ALPHA_VERSION;
|
||||
|
||||
@@ -1751,18 +1751,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
|
||||
}
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto poll = media->poll()) {
|
||||
if (!poll->closed()) {
|
||||
if (poll->voted() && !poll->quiz()) {
|
||||
_menu->addAction(tr::lng_polls_retract(tr::now), [=] {
|
||||
session->api().sendPollVotes(itemId, {});
|
||||
});
|
||||
}
|
||||
if (item->canStopPoll()) {
|
||||
_menu->addAction(tr::lng_polls_stop(tr::now), [=] {
|
||||
HistoryView::StopPoll(session, itemId);
|
||||
});
|
||||
}
|
||||
}
|
||||
HistoryView::AddPollActions(
|
||||
_menu,
|
||||
poll,
|
||||
item,
|
||||
HistoryView::Context::History);
|
||||
} else if (const auto contact = media->sharedContact()) {
|
||||
const auto phone = contact->phoneNumber;
|
||||
_menu->addAction(tr::lng_profile_copy_phone(tr::now), [=] {
|
||||
|
||||
@@ -868,6 +868,9 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||
const auto document = linkDocument
|
||||
? linkDocument->document().get()
|
||||
: nullptr;
|
||||
const auto poll = item
|
||||
? (item->media() ? item->media()->poll() : nullptr)
|
||||
: nullptr;
|
||||
const auto hasSelection = !request.selectedItems.empty()
|
||||
|| !request.selectedText.empty();
|
||||
|
||||
@@ -897,6 +900,8 @@ base::unique_qptr<Ui::PopupMenu> FillContextMenu(
|
||||
// });
|
||||
// AddToggleGroupingAction(result, linkPeer->peer());
|
||||
// }
|
||||
} else if (poll) {
|
||||
AddPollActions(result, poll, item, list->elementContext());
|
||||
} else if (!request.overSelection && view && !hasSelection) {
|
||||
const auto owner = &view->data()->history()->owner();
|
||||
const auto media = view->media();
|
||||
@@ -979,4 +984,30 @@ void StopPoll(not_null<Main::Session*> session, FullMsgId itemId) {
|
||||
stop));
|
||||
}
|
||||
|
||||
void AddPollActions(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
not_null<PollData*> poll,
|
||||
not_null<HistoryItem*> item,
|
||||
Context context) {
|
||||
if ((context != Context::History)
|
||||
&& (context != Context::Replies)
|
||||
&& (context != Context::Pinned)) {
|
||||
return;
|
||||
}
|
||||
if (poll->closed()) {
|
||||
return;
|
||||
}
|
||||
const auto itemId = item->fullId();
|
||||
if (poll->voted() && !poll->quiz()) {
|
||||
menu->addAction(tr::lng_polls_retract(tr::now), [=] {
|
||||
poll->session().api().sendPollVotes(itemId, {});
|
||||
});
|
||||
}
|
||||
if (item->canStopPoll()) {
|
||||
menu->addAction(tr::lng_polls_stop(tr::now), [=] {
|
||||
StopPoll(&poll->session(), itemId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace HistoryView
|
||||
|
||||
@@ -49,5 +49,10 @@ void CopyPostLink(
|
||||
FullMsgId itemId,
|
||||
Context context);
|
||||
void StopPoll(not_null<Main::Session*> session, FullMsgId itemId);
|
||||
void AddPollActions(
|
||||
not_null<Ui::PopupMenu*> menu,
|
||||
not_null<PollData*> poll,
|
||||
not_null<HistoryItem*> item,
|
||||
Context context);
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -321,6 +321,7 @@ rpl::producer<Ui::GroupCallBarContent> GroupCallTracker::ContentByCall(
|
||||
call->fullCountValue(
|
||||
) | rpl::start_with_next([=](int count) {
|
||||
state->current.count = count;
|
||||
state->current.shown = (count > 0);
|
||||
consumer.put_next_copy(state->current);
|
||||
}, lifetime);
|
||||
|
||||
|
||||
@@ -525,12 +525,36 @@ void TopBarWidget::setActiveChat(
|
||||
_activeChat = activeChat;
|
||||
return;
|
||||
}
|
||||
const auto peerChanged = (_activeChat.key.history()
|
||||
!= activeChat.key.history());
|
||||
|
||||
_activeChat = activeChat;
|
||||
_sendAction = sendAction;
|
||||
_titlePeerText.clear();
|
||||
_back->clearState();
|
||||
update();
|
||||
|
||||
if (peerChanged) {
|
||||
_activeChatLifetime.destroy();
|
||||
if (const auto history = _activeChat.key.history()) {
|
||||
session().changes().peerFlagsValue(
|
||||
history->peer,
|
||||
Data::PeerUpdate::Flag::GroupCall
|
||||
) | rpl::map([=] {
|
||||
return history->peer->groupCall();
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::map([](Data::GroupCall *call) {
|
||||
return call ? call->fullCountValue() : rpl::single(-1);
|
||||
}) | rpl::flatten_latest(
|
||||
) | rpl::map([](int count) {
|
||||
return (count == 0);
|
||||
}) | rpl::distinct_until_changed(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateControlsVisibility();
|
||||
updateControlsGeometry();
|
||||
}, _activeChatLifetime);
|
||||
}
|
||||
}
|
||||
updateUnreadBadge();
|
||||
refreshInfoButton();
|
||||
if (_menu) {
|
||||
@@ -722,7 +746,12 @@ void TopBarWidget::updateControlsVisibility() {
|
||||
_call->setVisible(historyMode && callsEnabled);
|
||||
const auto groupCallsEnabled = [&] {
|
||||
if (const auto peer = _activeChat.key.peer()) {
|
||||
return peer->canManageGroupCall();
|
||||
if (peer->canManageGroupCall()) {
|
||||
return true;
|
||||
} else if (const auto call = peer->groupCall()) {
|
||||
return (call->fullCount() == 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}();
|
||||
|
||||
@@ -130,6 +130,7 @@ private:
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
ActiveChat _activeChat;
|
||||
QString _customTitleText;
|
||||
rpl::lifetime _activeChatLifetime;
|
||||
|
||||
int _selectedCount = 0;
|
||||
bool _canDelete = false;
|
||||
|
||||
@@ -765,7 +765,9 @@ void Poll::draw(Painter &p, const QRect &r, TextSelection selection, crl::time m
|
||||
: nullptr;
|
||||
if (animation) {
|
||||
animation->percent.update(progress, anim::linear);
|
||||
animation->filling.update(progress, anim::linear);
|
||||
animation->filling.update(
|
||||
progress,
|
||||
showVotes() ? anim::easeOutCirc : anim::linear);
|
||||
animation->opacity.update(progress, anim::linear);
|
||||
}
|
||||
const auto height = paintAnswer(
|
||||
|
||||
@@ -360,6 +360,7 @@ OverlayWidget::OverlayWidget()
|
||||
setWindowFlags(Qt::FramelessWindowHint);
|
||||
}
|
||||
updateGeometry();
|
||||
updateControlsGeometry();
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
setAttribute(Qt::WA_TranslucentBackground, true);
|
||||
setMouseTracking(true);
|
||||
@@ -446,17 +447,16 @@ void OverlayWidget::moveToScreen() {
|
||||
: nullptr;
|
||||
const auto activeWindowScreen = widgetScreen(window);
|
||||
const auto myScreen = widgetScreen(this);
|
||||
// Wayland doesn't support positioning, but Qt emits screenChanged anyway
|
||||
// and geometry of the widget become broken
|
||||
if (activeWindowScreen
|
||||
&& myScreen != activeWindowScreen
|
||||
&& !Platform::IsWayland()) {
|
||||
if (activeWindowScreen && myScreen != activeWindowScreen) {
|
||||
windowHandle()->setScreen(activeWindowScreen);
|
||||
}
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void OverlayWidget::updateGeometry() {
|
||||
if (!Platform::IsMac()) {
|
||||
return;
|
||||
}
|
||||
const auto screen = windowHandle() && windowHandle()->screen()
|
||||
? windowHandle()->screen()
|
||||
: QApplication::primaryScreen();
|
||||
@@ -465,7 +465,13 @@ void OverlayWidget::updateGeometry() {
|
||||
return;
|
||||
}
|
||||
setGeometry(available);
|
||||
}
|
||||
|
||||
void OverlayWidget::resizeEvent(QResizeEvent *e) {
|
||||
updateControlsGeometry();
|
||||
}
|
||||
|
||||
void OverlayWidget::updateControlsGeometry() {
|
||||
auto navSkip = 2 * st::mediaviewControlMargin + st::mediaviewControlSize;
|
||||
_closeNav = myrtlrect(width() - st::mediaviewControlMargin - st::mediaviewControlSize, st::mediaviewControlMargin, st::mediaviewControlSize, st::mediaviewControlSize);
|
||||
_closeNavIcon = style::centerrect(_closeNav, st::mediaviewClose);
|
||||
@@ -478,6 +484,7 @@ void OverlayWidget::updateGeometry() {
|
||||
_photoRadialRect = QRect(QPoint((width() - st::radialSize.width()) / 2, (height() - st::radialSize.height()) / 2), st::radialSize);
|
||||
|
||||
resizeContentByScreenSize();
|
||||
updateControls();
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
@@ -55,10 +55,14 @@ class Pip;
|
||||
#define USE_OPENGL_OVERLAY_WIDGET
|
||||
#endif // Q_OS_MAC && !OS_MAC_OLD
|
||||
|
||||
struct OverlayParentTraits : Ui::RpWidgetDefaultTraits {
|
||||
static constexpr bool kSetZeroGeometry = false;
|
||||
};
|
||||
|
||||
#ifdef USE_OPENGL_OVERLAY_WIDGET
|
||||
using OverlayParent = Ui::RpWidgetWrap<QOpenGLWidget>;
|
||||
using OverlayParent = Ui::RpWidgetWrap<QOpenGLWidget, OverlayParentTraits>;
|
||||
#else // USE_OPENGL_OVERLAY_WIDGET
|
||||
using OverlayParent = Ui::RpWidget;
|
||||
using OverlayParent = Ui::RpWidgetWrap<QWidget, OverlayParentTraits>;
|
||||
#endif // USE_OPENGL_OVERLAY_WIDGET
|
||||
|
||||
class OverlayWidget final
|
||||
@@ -166,6 +170,7 @@ private:
|
||||
};
|
||||
|
||||
void paintEvent(QPaintEvent *e) override;
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
void wheelEvent(QWheelEvent *e) override;
|
||||
@@ -270,6 +275,7 @@ private:
|
||||
void updateDocSize();
|
||||
void updateControls();
|
||||
void updateActions();
|
||||
void updateControlsGeometry();
|
||||
void resizeCenteredControls();
|
||||
void resizeContentByScreenSize();
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ QByteArray DnsUserAgent() {
|
||||
static const auto kResult = QByteArray(
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/86.0.4240.198 Safari/537.36");
|
||||
"Chrome/87.0.4280.88 Safari/537.36");
|
||||
return kResult;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,45 +45,95 @@ bool ShowOpenWithSupported() {
|
||||
&& (Libs::gtk_app_chooser_dialog_new != nullptr)
|
||||
&& (Libs::gtk_app_chooser_get_app_info != nullptr)
|
||||
&& (Libs::gtk_app_chooser_get_type != nullptr)
|
||||
&& (Libs::gtk_widget_get_type != nullptr)
|
||||
&& (Libs::gtk_widget_get_window != nullptr)
|
||||
&& (Libs::gtk_widget_realize != nullptr)
|
||||
&& (Libs::gtk_widget_show != nullptr)
|
||||
&& (Libs::gtk_widget_destroy != nullptr);
|
||||
}
|
||||
|
||||
void HandleAppChooserResponse(
|
||||
GtkDialog *dialog,
|
||||
int responseId,
|
||||
GFile *file) {
|
||||
class OpenWithDialog : public QWindow {
|
||||
public:
|
||||
OpenWithDialog(const QString &filepath);
|
||||
~OpenWithDialog();
|
||||
|
||||
bool exec();
|
||||
|
||||
private:
|
||||
static void handleResponse(OpenWithDialog *dialog, int responseId);
|
||||
|
||||
GFile *_gfileInstance = nullptr;
|
||||
GtkWidget *_gtkWidget = nullptr;
|
||||
QEventLoop _loop;
|
||||
std::optional<bool> _result = std::nullopt;
|
||||
};
|
||||
|
||||
OpenWithDialog::OpenWithDialog(const QString &filepath)
|
||||
: _gfileInstance(g_file_new_for_path(filepath.toUtf8()))
|
||||
, _gtkWidget(Libs::gtk_app_chooser_dialog_new(
|
||||
nullptr,
|
||||
GTK_DIALOG_MODAL,
|
||||
_gfileInstance)) {
|
||||
g_signal_connect_swapped(
|
||||
_gtkWidget,
|
||||
"response",
|
||||
G_CALLBACK(handleResponse),
|
||||
this);
|
||||
}
|
||||
|
||||
OpenWithDialog::~OpenWithDialog() {
|
||||
Libs::gtk_widget_destroy(_gtkWidget);
|
||||
g_object_unref(_gfileInstance);
|
||||
}
|
||||
|
||||
bool OpenWithDialog::exec() {
|
||||
Libs::gtk_widget_realize(_gtkWidget);
|
||||
|
||||
if (const auto activeWindow = Core::App().activeWindow()) {
|
||||
Platform::internal::XSetTransientForHint(
|
||||
Libs::gtk_widget_get_window(_gtkWidget),
|
||||
activeWindow->widget().get()->windowHandle()->winId());
|
||||
}
|
||||
|
||||
QGuiApplicationPrivate::showModalWindow(this);
|
||||
Libs::gtk_widget_show(_gtkWidget);
|
||||
|
||||
if (!_result.has_value()) {
|
||||
_loop.exec();
|
||||
}
|
||||
|
||||
QGuiApplicationPrivate::hideModalWindow(this);
|
||||
return *_result;
|
||||
}
|
||||
|
||||
void OpenWithDialog::handleResponse(OpenWithDialog *dialog, int responseId) {
|
||||
GAppInfo *chosenAppInfo = nullptr;
|
||||
dialog->_result = true;
|
||||
|
||||
switch (responseId) {
|
||||
case GTK_RESPONSE_OK:
|
||||
chosenAppInfo = Libs::gtk_app_chooser_get_app_info(
|
||||
Libs::gtk_app_chooser_cast(dialog));
|
||||
Libs::gtk_app_chooser_cast(dialog->_gtkWidget));
|
||||
|
||||
if (chosenAppInfo) {
|
||||
GList *uris = nullptr;
|
||||
uris = g_list_prepend(uris, g_file_get_uri(file));
|
||||
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);
|
||||
}
|
||||
|
||||
g_object_unref(file);
|
||||
Libs::gtk_widget_destroy(Libs::gtk_widget_cast(dialog));
|
||||
break;
|
||||
|
||||
case GTK_RESPONSE_CANCEL:
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
g_object_unref(file);
|
||||
Libs::gtk_widget_destroy(Libs::gtk_widget_cast(dialog));
|
||||
break;
|
||||
|
||||
default:
|
||||
dialog->_result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
dialog->_loop.quit();
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
@@ -141,30 +191,7 @@ bool UnsafeShowOpenWith(const QString &filepath) {
|
||||
}
|
||||
|
||||
const auto absolutePath = QFileInfo(filepath).absoluteFilePath();
|
||||
auto gfileInstance = g_file_new_for_path(absolutePath.toUtf8());
|
||||
|
||||
auto appChooserDialog = Libs::gtk_app_chooser_dialog_new(
|
||||
nullptr,
|
||||
GTK_DIALOG_MODAL,
|
||||
gfileInstance);
|
||||
|
||||
g_signal_connect(
|
||||
appChooserDialog,
|
||||
"response",
|
||||
G_CALLBACK(HandleAppChooserResponse),
|
||||
gfileInstance);
|
||||
|
||||
Libs::gtk_widget_realize(appChooserDialog);
|
||||
|
||||
if (const auto activeWindow = Core::App().activeWindow()) {
|
||||
Platform::internal::XSetTransientForHint(
|
||||
Libs::gtk_widget_get_window(appChooserDialog),
|
||||
activeWindow->widget().get()->windowHandle()->winId());
|
||||
}
|
||||
|
||||
Libs::gtk_widget_show(appChooserDialog);
|
||||
|
||||
return true;
|
||||
return OpenWithDialog(absolutePath).exec();
|
||||
#else // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
return false;
|
||||
#endif // TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
@@ -9,8 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "platform/linux/linux_gdk_helper.h"
|
||||
|
||||
#include "platform/linux/linux_libs.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/linux/base_xcb_utilities_linux.h"
|
||||
|
||||
extern "C" {
|
||||
#undef signals
|
||||
@@ -33,6 +31,9 @@ GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone;
|
||||
#define GdkDrawable GdkWindow
|
||||
|
||||
// Gtk 2
|
||||
using f_gdk_x11_drawable_get_xdisplay = Display*(*)(GdkDrawable*);
|
||||
f_gdk_x11_drawable_get_xdisplay gdk_x11_drawable_get_xdisplay = nullptr;
|
||||
|
||||
using f_gdk_x11_drawable_get_xid = XID(*)(GdkDrawable*);
|
||||
f_gdk_x11_drawable_get_xid gdk_x11_drawable_get_xid = nullptr;
|
||||
|
||||
@@ -46,6 +47,12 @@ inline bool gdk_is_x11_window_check(Object *obj) {
|
||||
return Libs::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;
|
||||
|
||||
using f_gdk_x11_display_get_xdisplay = Display*(*)(GdkDisplay *display);
|
||||
f_gdk_x11_display_get_xdisplay gdk_x11_display_get_xdisplay = nullptr;
|
||||
|
||||
using f_gdk_x11_window_get_xid = Window(*)(GdkWindow *window);
|
||||
f_gdk_x11_window_get_xid gdk_x11_window_get_xid = nullptr;
|
||||
|
||||
@@ -53,6 +60,7 @@ bool GdkHelperLoadGtk2(QLibrary &lib) {
|
||||
#if defined DESKTOP_APP_USE_PACKAGED && !defined DESKTOP_APP_USE_PACKAGED_LAZY
|
||||
return false;
|
||||
#else // DESKTOP_APP_USE_PACKAGED && !DESKTOP_APP_USE_PACKAGED_LAZY
|
||||
if (!LOAD_SYMBOL(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false;
|
||||
if (!LOAD_SYMBOL(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false;
|
||||
return true;
|
||||
#endif // !DESKTOP_APP_USE_PACKAGED || DESKTOP_APP_USE_PACKAGED_LAZY
|
||||
@@ -60,6 +68,8 @@ bool GdkHelperLoadGtk2(QLibrary &lib) {
|
||||
|
||||
bool GdkHelperLoadGtk3(QLibrary &lib) {
|
||||
if (!LOAD_SYMBOL(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false;
|
||||
if (!LOAD_SYMBOL(lib, "gdk_window_get_display", gdk_window_get_display)) return false;
|
||||
if (!LOAD_SYMBOL(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false;
|
||||
if (!LOAD_SYMBOL(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false;
|
||||
return true;
|
||||
}
|
||||
@@ -79,28 +89,14 @@ bool GdkHelperLoaded() {
|
||||
|
||||
void XSetTransientForHint(GdkWindow *window, quintptr winId) {
|
||||
if (gdk_helper_loaded == GtkLoaded::Gtk2) {
|
||||
if (!IsWayland()) {
|
||||
xcb_change_property(
|
||||
base::Platform::XCB::GetConnectionFromQt(),
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
gdk_x11_drawable_get_xid(window),
|
||||
XCB_ATOM_WM_TRANSIENT_FOR,
|
||||
XCB_ATOM_WINDOW,
|
||||
32,
|
||||
1,
|
||||
&winId);
|
||||
}
|
||||
::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window),
|
||||
gdk_x11_drawable_get_xid(window),
|
||||
winId);
|
||||
} else if (gdk_helper_loaded == GtkLoaded::Gtk3) {
|
||||
if (!IsWayland() && gdk_is_x11_window_check(window)) {
|
||||
xcb_change_property(
|
||||
base::Platform::XCB::GetConnectionFromQt(),
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
gdk_x11_window_get_xid(window),
|
||||
XCB_ATOM_WM_TRANSIENT_FOR,
|
||||
XCB_ATOM_WINDOW,
|
||||
32,
|
||||
1,
|
||||
&winId);
|
||||
if (gdk_is_x11_window_check(window)) {
|
||||
::XSetTransientForHint(gdk_x11_display_get_xdisplay(gdk_window_get_display(window)),
|
||||
gdk_x11_window_get_xid(window),
|
||||
winId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,7 +74,6 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_get_type", gtk_widget_get_type)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
|
||||
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false;
|
||||
@@ -236,7 +235,6 @@ f_gtk_widget_get_window gtk_widget_get_window = nullptr;
|
||||
f_gtk_widget_realize gtk_widget_realize = nullptr;
|
||||
f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete = nullptr;
|
||||
f_gtk_widget_destroy gtk_widget_destroy = nullptr;
|
||||
f_gtk_widget_get_type gtk_widget_get_type = nullptr;
|
||||
f_gtk_clipboard_get gtk_clipboard_get = nullptr;
|
||||
f_gtk_clipboard_store gtk_clipboard_store = nullptr;
|
||||
f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents = nullptr;
|
||||
|
||||
@@ -235,14 +235,6 @@ inline GtkWindow *gtk_window_cast(Object *obj) {
|
||||
return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type());
|
||||
}
|
||||
|
||||
typedef GType (*f_gtk_widget_get_type)(void) G_GNUC_CONST;
|
||||
extern f_gtk_widget_get_type gtk_widget_get_type;
|
||||
|
||||
template <typename Object>
|
||||
inline GtkWidget *gtk_widget_cast(Object *obj) {
|
||||
return g_type_cic_helper<GtkWidget, Object>(obj, gtk_widget_get_type());
|
||||
}
|
||||
|
||||
typedef GType (*f_gtk_app_chooser_get_type)(void) G_GNUC_CONST;
|
||||
extern f_gtk_app_chooser_get_type gtk_app_chooser_get_type;
|
||||
|
||||
|
||||
@@ -15,11 +15,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include <private/qwaylandwindow_p.h>
|
||||
#include <private/qwaylandshellsurface_p.h>
|
||||
|
||||
#include <connection_thread.h>
|
||||
#include <registry.h>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 13, 0) && !defined DESKTOP_APP_QT_PATCHED
|
||||
#include <wayland-client.h>
|
||||
#endif // Qt < 5.13 && !DESKTOP_APP_QT_PATCHED
|
||||
|
||||
using QtWaylandClient::QWaylandWindow;
|
||||
using namespace KWayland::Client;
|
||||
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
@@ -51,15 +55,75 @@ enum wl_shell_surface_resize WlResizeFromEdges(Qt::Edges edges) {
|
||||
|
||||
} // namespace
|
||||
|
||||
WaylandIntegration::WaylandIntegration() {
|
||||
class WaylandIntegration::Private : public QObject {
|
||||
public:
|
||||
Private();
|
||||
|
||||
[[nodiscard]] Registry ®istry() {
|
||||
return _registry;
|
||||
}
|
||||
|
||||
[[nodiscard]] QEventLoop &interfacesLoop() {
|
||||
return _interfacesLoop;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool interfacesAnnounced() const {
|
||||
return _interfacesAnnounced;
|
||||
}
|
||||
|
||||
private:
|
||||
ConnectionThread _connection;
|
||||
Registry _registry;
|
||||
QEventLoop _interfacesLoop;
|
||||
bool _interfacesAnnounced = false;
|
||||
};
|
||||
|
||||
WaylandIntegration::Private::Private() {
|
||||
connect(&_connection, &ConnectionThread::connected, [=] {
|
||||
LOG(("Successfully connected to Wayland server at socket: %1")
|
||||
.arg(_connection.socketName()));
|
||||
|
||||
_registry.create(&_connection);
|
||||
_registry.setup();
|
||||
});
|
||||
|
||||
connect(
|
||||
&_connection,
|
||||
&ConnectionThread::connectionDied,
|
||||
&_registry,
|
||||
&Registry::destroy);
|
||||
|
||||
connect(&_registry, &Registry::interfacesAnnounced, [=] {
|
||||
_interfacesAnnounced = true;
|
||||
_interfacesLoop.quit();
|
||||
});
|
||||
|
||||
_connection.initConnection();
|
||||
}
|
||||
|
||||
WaylandIntegration::WaylandIntegration()
|
||||
: _private(std::make_unique<Private>()) {
|
||||
}
|
||||
|
||||
WaylandIntegration::~WaylandIntegration() = default;
|
||||
|
||||
WaylandIntegration *WaylandIntegration::Instance() {
|
||||
if (!IsWayland()) return nullptr;
|
||||
static WaylandIntegration instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void WaylandIntegration::waitForInterfaceAnnounce() {
|
||||
if (!_private->interfacesAnnounced()) {
|
||||
_private->interfacesLoop().exec();
|
||||
}
|
||||
}
|
||||
|
||||
bool WaylandIntegration::supportsXdgDecoration() {
|
||||
return _private->registry().hasInterface(
|
||||
Registry::Interface::XdgDecorationUnstableV1);
|
||||
}
|
||||
|
||||
bool WaylandIntegration::startMove(QWindow *window) {
|
||||
// There are startSystemMove on Qt 5.15
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) && !defined DESKTOP_APP_QT_PATCHED
|
||||
|
||||
@@ -15,12 +15,18 @@ namespace internal {
|
||||
class WaylandIntegration {
|
||||
public:
|
||||
static WaylandIntegration *Instance();
|
||||
void waitForInterfaceAnnounce();
|
||||
bool supportsXdgDecoration();
|
||||
bool startMove(QWindow *window);
|
||||
bool startResize(QWindow *window, Qt::Edges edges);
|
||||
bool showWindowMenu(QWindow *window);
|
||||
|
||||
private:
|
||||
WaylandIntegration();
|
||||
~WaylandIntegration();
|
||||
|
||||
class Private;
|
||||
const std::unique_ptr<Private> _private;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
@@ -12,15 +12,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
namespace Platform {
|
||||
namespace internal {
|
||||
|
||||
class WaylandIntegration::Private {
|
||||
};
|
||||
|
||||
WaylandIntegration::WaylandIntegration() {
|
||||
}
|
||||
|
||||
WaylandIntegration::~WaylandIntegration() = default;
|
||||
|
||||
WaylandIntegration *WaylandIntegration::Instance() {
|
||||
if (!IsWayland()) return nullptr;
|
||||
static WaylandIntegration instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void WaylandIntegration::waitForInterfaceAnnounce() {
|
||||
}
|
||||
|
||||
bool WaylandIntegration::supportsXdgDecoration() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WaylandIntegration::startMove(QWindow *window) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -23,13 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "storage/localstorage.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "media/player/media_player_instance.h"
|
||||
#include "media/audio/media_audio.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "base/platform/linux/base_xcb_utilities_linux.h"
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "platform/linux/linux_gsd_media_keys.h"
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "base/call_delayed.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
@@ -407,10 +402,8 @@ bool UseUnityCounter() {
|
||||
|
||||
return Result;
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
bool IsSNIAvailable() {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
auto message = QDBusMessage::createMethodCall(
|
||||
kSNIWatcherService.utf16(),
|
||||
kSNIWatcherObjectPath.utf16(),
|
||||
@@ -418,7 +411,7 @@ bool IsSNIAvailable() {
|
||||
qsl("Get"));
|
||||
|
||||
message.setArguments({
|
||||
kSNIWatcherService.utf16(),
|
||||
kSNIWatcherInterface.utf16(),
|
||||
qsl("IsStatusNotifierHostRegistered")
|
||||
});
|
||||
|
||||
@@ -430,7 +423,6 @@ bool IsSNIAvailable() {
|
||||
} else if (reply.error().type() != QDBusError::ServiceUnknown) {
|
||||
LOG(("SNI Error: %1").arg(reply.error().message()));
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -444,7 +436,6 @@ quint32 djbStringHash(QString string) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
bool IsAppMenuSupported() {
|
||||
const auto interface = QDBusConnection::sessionBus().interface();
|
||||
|
||||
@@ -517,10 +508,9 @@ MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||
}
|
||||
|
||||
void MainWindow::initHook() {
|
||||
_sniAvailable = IsSNIAvailable();
|
||||
LOG(("System tray available: %1").arg(Logs::b(trayAvailable())));
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
_sniAvailable = IsSNIAvailable();
|
||||
|
||||
_sniDBusProxy = g_dbus_proxy_new_for_bus_sync(
|
||||
G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_NONE,
|
||||
@@ -584,21 +574,11 @@ void MainWindow::initHook() {
|
||||
} else {
|
||||
LOG(("Not using Unity launcher counter."));
|
||||
}
|
||||
|
||||
Media::Player::instance()->updatedNotifier(
|
||||
) | rpl::start_with_next([=](const Media::Player::TrackState &state) {
|
||||
if (!Media::Player::IsStoppedOrStopping(state.state)) {
|
||||
if (!_gsdMediaKeys) {
|
||||
_gsdMediaKeys = std::make_unique<internal::GSDMediaKeys>();
|
||||
}
|
||||
} else if (_gsdMediaKeys) {
|
||||
_gsdMediaKeys = nullptr;
|
||||
}
|
||||
}, lifetime());
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
updateWaylandDecorationColors();
|
||||
LOG(("System tray available: %1").arg(Logs::b(trayAvailable())));
|
||||
|
||||
updateWaylandDecorationColors();
|
||||
style::PaletteChanged(
|
||||
) | rpl::start_with_next([=] {
|
||||
updateWaylandDecorationColors();
|
||||
@@ -842,25 +822,28 @@ void MainWindow::updateIconCounters() {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
if (UseUnityCounter()) {
|
||||
const auto launcherUrl = "application://" + GetLauncherFilename();
|
||||
// Gnome requires that count is a 64bit integer
|
||||
const qint64 counterSlice = std::min(counter, 9999);
|
||||
QVariantMap dbusUnityProperties;
|
||||
if (counter > 0) {
|
||||
// Gnome requires that count is a 64bit integer
|
||||
dbusUnityProperties.insert(
|
||||
"count",
|
||||
(qint64) ((counter > 9999)
|
||||
? 9999
|
||||
: counter));
|
||||
dbusUnityProperties.insert("count-visible", true);
|
||||
|
||||
if (counterSlice > 0) {
|
||||
dbusUnityProperties["count"] = counterSlice;
|
||||
dbusUnityProperties["count-visible"] = true;
|
||||
} else {
|
||||
dbusUnityProperties.insert("count-visible", false);
|
||||
dbusUnityProperties["count-visible"] = false;
|
||||
}
|
||||
QDBusMessage signal = QDBusMessage::createSignal(
|
||||
|
||||
auto signal = QDBusMessage::createSignal(
|
||||
"/com/canonical/unity/launcherentry/"
|
||||
+ QString::number(djbStringHash(launcherUrl)),
|
||||
"com.canonical.Unity.LauncherEntry",
|
||||
"Update");
|
||||
signal << launcherUrl;
|
||||
signal << dbusUnityProperties;
|
||||
|
||||
signal.setArguments({
|
||||
launcherUrl,
|
||||
dbusUnityProperties
|
||||
});
|
||||
|
||||
QDBusConnection::sessionBus().send(signal);
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,6 @@ typedef struct _GDBusProxy GDBusProxy;
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
namespace Platform {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
namespace internal {
|
||||
class GSDMediaKeys;
|
||||
} // namespace internal
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
public:
|
||||
@@ -93,8 +88,6 @@ private:
|
||||
bool _appMenuSupported = false;
|
||||
DBusMenuExporter *_mainMenuExporter = nullptr;
|
||||
|
||||
std::unique_ptr<internal::GSDMediaKeys> _gsdMediaKeys;
|
||||
|
||||
QMenu *psMainMenu = nullptr;
|
||||
QAction *psLogout = nullptr;
|
||||
QAction *psUndo = nullptr;
|
||||
|
||||
@@ -17,7 +17,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "main/main_session.h"
|
||||
#include "lang/lang_keys.h"
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include <QtCore/QVersionNumber>
|
||||
#include <QtDBus/QDBusConnection>
|
||||
#include <QtDBus/QDBusMessage>
|
||||
@@ -29,12 +28,9 @@ extern "C" {
|
||||
#include <gio/gio.h>
|
||||
#define signals public
|
||||
} // extern "C"
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
namespace {
|
||||
|
||||
constexpr auto kDBusTimeout = 30000;
|
||||
@@ -615,16 +611,13 @@ void NotificationData::notificationReplied(uint id, const QString &text) {
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
bool SkipAudio() {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
if (Supported()
|
||||
&& GetCapabilities().contains(qsl("inhibitions"))
|
||||
&& !InhibitedNotSupported) {
|
||||
return Inhibited();
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -638,18 +631,12 @@ bool SkipFlashBounce() {
|
||||
}
|
||||
|
||||
bool Supported() {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
return NotificationsSupported;
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<Window::Notifications::Manager> Create(
|
||||
Window::Notifications::System *system) {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
GetSupported();
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
if ((Core::App().settings().nativeNotifications() && Supported())
|
||||
|| IsWayland()) {
|
||||
@@ -659,27 +646,6 @@ std::unique_ptr<Window::Notifications::Manager> Create(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
class Manager::Private {
|
||||
public:
|
||||
using Type = Window::Notifications::CachedUserpics::Type;
|
||||
explicit Private(not_null<Manager*> manager, Type type) {}
|
||||
|
||||
void showNotification(
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
||||
MsgId msgId,
|
||||
const QString &title,
|
||||
const QString &subtitle,
|
||||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) {}
|
||||
void clearAll() {}
|
||||
void clearFromHistory(not_null<History*> history) {}
|
||||
void clearFromSession(not_null<Main::Session*> session) {}
|
||||
void clearNotification(NotificationId id) {}
|
||||
};
|
||||
#else // DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
class Manager::Private {
|
||||
public:
|
||||
using Type = Window::Notifications::CachedUserpics::Type;
|
||||
@@ -866,7 +832,6 @@ void Manager::Private::clearNotification(NotificationId id) {
|
||||
Manager::Private::~Private() {
|
||||
clearAll();
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
Manager::Manager(not_null<Window::Notifications::System*> system)
|
||||
: NativeManager(system)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
This file is part of Telegram Desktop,
|
||||
the official desktop application for the Telegram messaging service.
|
||||
|
||||
For license and copyright information please follow this link:
|
||||
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
|
||||
namespace Platform {
|
||||
namespace Notifications {
|
||||
|
||||
bool SkipAudio() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkipToast() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SkipFlashBounce() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Supported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<Window::Notifications::Manager> Create(
|
||||
Window::Notifications::System *system) {
|
||||
if (IsWayland()) {
|
||||
return std::make_unique<Window::Notifications::DummyManager>(system);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Notifications
|
||||
} // namespace Platform
|
||||
@@ -24,6 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "window/window_controller.h"
|
||||
#include "core/application.h"
|
||||
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
#include "platform/linux/linux_gsd_media_keys.h"
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtCore/QStandardPaths>
|
||||
@@ -521,6 +525,18 @@ Window::Control GtkKeywordToWindowControl(const QString &keyword) {
|
||||
|
||||
} // namespace
|
||||
|
||||
void SetWatchingMediaKeys(bool watching) {
|
||||
#ifndef DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
static std::unique_ptr<internal::GSDMediaKeys> Instance;
|
||||
|
||||
if (watching && !Instance) {
|
||||
Instance = std::make_unique<internal::GSDMediaKeys>();
|
||||
} else if (!watching && Instance) {
|
||||
Instance = nullptr;
|
||||
}
|
||||
#endif // !DESKTOP_APP_DISABLE_DBUS_INTEGRATION
|
||||
}
|
||||
|
||||
void SetApplicationIcon(const QIcon &icon) {
|
||||
QApplication::setWindowIcon(icon);
|
||||
}
|
||||
@@ -1210,6 +1226,11 @@ void start() {
|
||||
|
||||
Libs::start();
|
||||
MainWindow::LibsLoaded();
|
||||
|
||||
// wait for interface announce to know if native window frame is supported
|
||||
if (const auto waylandIntegration = WaylandIntegration::Instance()) {
|
||||
waylandIntegration->waitForInterfaceAnnounce();
|
||||
}
|
||||
}
|
||||
|
||||
void finish() {
|
||||
|
||||
@@ -17,9 +17,6 @@ class LocationPoint;
|
||||
|
||||
namespace Platform {
|
||||
|
||||
inline void SetWatchingMediaKeys(bool watching) {
|
||||
}
|
||||
|
||||
bool InFlatpak();
|
||||
bool InSnap();
|
||||
bool IsStaticBinary();
|
||||
|
||||
@@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "platform/linux/window_title_linux.h"
|
||||
|
||||
#include "platform/linux/linux_desktop_environment.h"
|
||||
#include "platform/linux/linux_wayland_integration.h"
|
||||
#include "base/platform/base_platform_info.h"
|
||||
|
||||
namespace Platform {
|
||||
@@ -24,9 +24,10 @@ bool SystemMoveResizeSupported() {
|
||||
} // namespace
|
||||
|
||||
bool AllowNativeWindowFrameToggle() {
|
||||
const auto waylandIntegration = internal::WaylandIntegration::Instance();
|
||||
return SystemMoveResizeSupported()
|
||||
// https://gitlab.gnome.org/GNOME/mutter/-/issues/217
|
||||
&& !(DesktopEnvironment::IsGnome() && IsWayland());
|
||||
&& (!waylandIntegration
|
||||
|| waylandIntegration->supportsXdgDecoration());
|
||||
}
|
||||
|
||||
object_ptr<Window::TitleWidget> CreateTitleWidget(QWidget *parent) {
|
||||
|
||||
@@ -30,11 +30,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "webrtc/webrtc_media_devices.h"
|
||||
#include "webrtc/webrtc_video_track.h"
|
||||
#include "webrtc/webrtc_audio_input_tester.h"
|
||||
#include "webrtc/webrtc_create_adm.h" // Webrtc::Backend.
|
||||
#include "tgcalls/VideoCaptureInterface.h"
|
||||
#include "facades.h"
|
||||
#include "app.h" // App::restart().
|
||||
#include "styles/style_layers.h"
|
||||
|
||||
namespace Settings {
|
||||
namespace {
|
||||
|
||||
using namespace Webrtc;
|
||||
|
||||
} // namespace
|
||||
|
||||
Calls::Calls(
|
||||
QWidget *parent,
|
||||
@@ -58,7 +65,7 @@ void Calls::setupContent() {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto cameras = Webrtc::GetVideoInputList();
|
||||
const auto cameras = GetVideoInputList();
|
||||
if (!cameras.empty()) {
|
||||
const auto hasCall = (Core::App().calls().currentCall() != nullptr);
|
||||
|
||||
@@ -66,16 +73,16 @@ void Calls::setupContent() {
|
||||
const auto capturer = capturerOwner.get();
|
||||
content->lifetime().add([owner = std::move(capturerOwner)]{});
|
||||
|
||||
const auto track = content->lifetime().make_state<Webrtc::VideoTrack>(
|
||||
const auto track = content->lifetime().make_state<VideoTrack>(
|
||||
(hasCall
|
||||
? Webrtc::VideoState::Inactive
|
||||
: Webrtc::VideoState::Active));
|
||||
? VideoState::Inactive
|
||||
: VideoState::Active));
|
||||
|
||||
const auto currentCameraName = [&] {
|
||||
const auto i = ranges::find(
|
||||
cameras,
|
||||
settings.callVideoInputDeviceId(),
|
||||
&Webrtc::VideoInput::id);
|
||||
&VideoInput::id);
|
||||
return (i != end(cameras))
|
||||
? i->name
|
||||
: tr::lng_settings_call_device_default(tr::now);
|
||||
@@ -93,15 +100,15 @@ void Calls::setupContent() {
|
||||
),
|
||||
st::settingsButton
|
||||
)->addClickHandler([=] {
|
||||
const auto &devices = Webrtc::GetVideoInputList();
|
||||
const auto &devices = GetVideoInputList();
|
||||
const auto options = ranges::view::concat(
|
||||
ranges::view::single(tr::lng_settings_call_device_default(tr::now)),
|
||||
devices | ranges::view::transform(&Webrtc::VideoInput::name)
|
||||
devices | ranges::view::transform(&VideoInput::name)
|
||||
) | ranges::to_vector;
|
||||
const auto i = ranges::find(
|
||||
devices,
|
||||
Core::App().settings().callVideoInputDeviceId(),
|
||||
&Webrtc::VideoInput::id);
|
||||
&VideoInput::id);
|
||||
const auto currentOption = (i != end(devices))
|
||||
? int(i - begin(devices) + 1)
|
||||
: 0;
|
||||
@@ -159,11 +166,11 @@ void Calls::setupContent() {
|
||||
Core::App().calls().currentCallValue(
|
||||
) | rpl::start_with_next([=](::Calls::Call *value) {
|
||||
if (value) {
|
||||
track->setState(Webrtc::VideoState::Inactive);
|
||||
track->setState(VideoState::Inactive);
|
||||
bubbleWrap->resize(bubbleWrap->width(), 0);
|
||||
} else {
|
||||
capturer->setPreferredAspectRatio(0.);
|
||||
track->setState(Webrtc::VideoState::Active);
|
||||
track->setState(VideoState::Active);
|
||||
capturer->setOutput(track->sink());
|
||||
}
|
||||
}, content->lifetime());
|
||||
@@ -252,6 +259,22 @@ void Calls::setupContent() {
|
||||
// }, content->lifetime());
|
||||
//#endif // Q_OS_MAC && !OS_MAC_STORE
|
||||
|
||||
const auto backend = [&]() -> QString {
|
||||
using namespace Webrtc;
|
||||
switch (settings.callAudioBackend()) {
|
||||
case Backend::OpenAL: return "OpenAL";
|
||||
case Backend::ADM: return "WebRTC ADM";
|
||||
case Backend::ADM2: return "WebRTC ADM2";
|
||||
}
|
||||
Unexpected("Value in backend.");
|
||||
}();
|
||||
AddButton(
|
||||
content,
|
||||
rpl::single("Call audio backend: " + backend),
|
||||
st::settingsButton
|
||||
)->addClickHandler([] {
|
||||
Ui::show(ChooseAudioBackendBox());
|
||||
});
|
||||
AddButton(
|
||||
content,
|
||||
tr::lng_settings_call_open_system_prefs(),
|
||||
@@ -300,27 +323,30 @@ void Calls::requestPermissionAndStartTestingMicrophone() {
|
||||
|
||||
void Calls::startTestingMicrophone() {
|
||||
_levelUpdateTimer.callEach(kMicTestUpdateInterval);
|
||||
_micTester = std::make_unique<Webrtc::AudioInputTester>(
|
||||
_micTester = std::make_unique<AudioInputTester>(
|
||||
Core::App().settings().callAudioBackend(),
|
||||
Core::App().settings().callInputDeviceId());
|
||||
}
|
||||
|
||||
QString CurrentAudioOutputName() {
|
||||
const auto list = Webrtc::GetAudioOutputList();
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto list = GetAudioOutputList(settings.callAudioBackend());
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
Core::App().settings().callOutputDeviceId(),
|
||||
&Webrtc::AudioOutput::id);
|
||||
settings.callOutputDeviceId(),
|
||||
&AudioOutput::id);
|
||||
return (i != end(list))
|
||||
? i->name
|
||||
: tr::lng_settings_call_device_default(tr::now);
|
||||
}
|
||||
|
||||
QString CurrentAudioInputName() {
|
||||
const auto list = Webrtc::GetAudioInputList();
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto list = GetAudioInputList(settings.callAudioBackend());
|
||||
const auto i = ranges::find(
|
||||
list,
|
||||
Core::App().settings().callInputDeviceId(),
|
||||
&Webrtc::AudioInput::id);
|
||||
settings.callInputDeviceId(),
|
||||
&AudioInput::id);
|
||||
return (i != end(list))
|
||||
? i->name
|
||||
: tr::lng_settings_call_device_default(tr::now);
|
||||
@@ -330,21 +356,22 @@ object_ptr<SingleChoiceBox> ChooseAudioOutputBox(
|
||||
Fn<void(QString id, QString name)> chosen,
|
||||
const style::Checkbox *st,
|
||||
const style::Radio *radioSt) {
|
||||
const auto &devices = Webrtc::GetAudioOutputList();
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto list = GetAudioOutputList(settings.callAudioBackend());
|
||||
const auto options = ranges::view::concat(
|
||||
ranges::view::single(tr::lng_settings_call_device_default(tr::now)),
|
||||
devices | ranges::view::transform(&Webrtc::AudioOutput::name)
|
||||
list | ranges::view::transform(&AudioOutput::name)
|
||||
) | ranges::to_vector;
|
||||
const auto i = ranges::find(
|
||||
devices,
|
||||
Core::App().settings().callOutputDeviceId(),
|
||||
&Webrtc::AudioOutput::id);
|
||||
const auto currentOption = (i != end(devices))
|
||||
? int(i - begin(devices) + 1)
|
||||
list,
|
||||
settings.callOutputDeviceId(),
|
||||
&AudioOutput::id);
|
||||
const auto currentOption = (i != end(list))
|
||||
? int(i - begin(list) + 1)
|
||||
: 0;
|
||||
const auto save = [=](int option) {
|
||||
const auto deviceId = option
|
||||
? devices[option - 1].id
|
||||
? list[option - 1].id
|
||||
: "default";
|
||||
Core::App().calls().setCurrentAudioDevice(false, deviceId);
|
||||
chosen(deviceId, options[option]);
|
||||
@@ -362,21 +389,22 @@ object_ptr<SingleChoiceBox> ChooseAudioInputBox(
|
||||
Fn<void(QString id, QString name)> chosen,
|
||||
const style::Checkbox *st,
|
||||
const style::Radio *radioSt) {
|
||||
const auto devices = Webrtc::GetAudioInputList();
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto list = GetAudioInputList(settings.callAudioBackend());
|
||||
const auto options = ranges::view::concat(
|
||||
ranges::view::single(tr::lng_settings_call_device_default(tr::now)),
|
||||
devices | ranges::view::transform(&Webrtc::AudioInput::name)
|
||||
list | ranges::view::transform(&AudioInput::name)
|
||||
) | ranges::to_vector;
|
||||
const auto i = ranges::find(
|
||||
devices,
|
||||
list,
|
||||
Core::App().settings().callInputDeviceId(),
|
||||
&Webrtc::AudioInput::id);
|
||||
const auto currentOption = (i != end(devices))
|
||||
? int(i - begin(devices) + 1)
|
||||
&AudioInput::id);
|
||||
const auto currentOption = (i != end(list))
|
||||
? int(i - begin(list) + 1)
|
||||
: 0;
|
||||
const auto save = [=](int option) {
|
||||
const auto deviceId = option
|
||||
? devices[option - 1].id
|
||||
? list[option - 1].id
|
||||
: "default";
|
||||
Core::App().calls().setCurrentAudioDevice(true, deviceId);
|
||||
chosen(deviceId, options[option]);
|
||||
@@ -390,5 +418,33 @@ object_ptr<SingleChoiceBox> ChooseAudioInputBox(
|
||||
radioSt);
|
||||
}
|
||||
|
||||
object_ptr<SingleChoiceBox> ChooseAudioBackendBox(
|
||||
const style::Checkbox *st,
|
||||
const style::Radio *radioSt) {
|
||||
const auto &settings = Core::App().settings();
|
||||
const auto list = GetAudioInputList(settings.callAudioBackend());
|
||||
const auto options = std::vector<QString>{
|
||||
"OpenAL",
|
||||
"Webrtc ADM",
|
||||
#ifdef Q_OS_WIN
|
||||
"Webrtc ADM2",
|
||||
#endif // Q_OS_WIN
|
||||
};
|
||||
const auto currentOption = static_cast<int>(settings.callAudioBackend());
|
||||
const auto save = [=](int option) {
|
||||
Core::App().settings().setCallAudioBackend(
|
||||
static_cast<Webrtc::Backend>(option));
|
||||
Core::App().saveSettings();
|
||||
App::restart();
|
||||
};
|
||||
return Box<SingleChoiceBox>(
|
||||
rpl::single<QString>("Calls audio backend"),
|
||||
options,
|
||||
currentOption,
|
||||
save,
|
||||
st,
|
||||
radioSt);
|
||||
}
|
||||
|
||||
} // namespace Settings
|
||||
|
||||
|
||||
@@ -69,6 +69,9 @@ inline constexpr auto kMicTestAnimationDuration = crl::time(200);
|
||||
Fn<void(QString id, QString name)> chosen,
|
||||
const style::Checkbox *st = nullptr,
|
||||
const style::Radio *radioSt = nullptr);
|
||||
[[nodiscard]] object_ptr<SingleChoiceBox> ChooseAudioBackendBox(
|
||||
const style::Checkbox *st = nullptr,
|
||||
const style::Radio *radioSt = nullptr);
|
||||
|
||||
} // namespace Settings
|
||||
|
||||
|
||||
@@ -248,6 +248,30 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
class DummyManager : public NativeManager {
|
||||
public:
|
||||
using NativeManager::NativeManager;
|
||||
|
||||
protected:
|
||||
void doShowNativeNotification(
|
||||
not_null<PeerData*> peer,
|
||||
std::shared_ptr<Data::CloudImageView> &userpicView,
|
||||
MsgId msgId,
|
||||
const QString &title,
|
||||
const QString &subtitle,
|
||||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) override {
|
||||
}
|
||||
void doClearAllFast() override {
|
||||
}
|
||||
void doClearFromHistory(not_null<History*> history) override {
|
||||
}
|
||||
void doClearFromSession(not_null<Main::Session*> session) override {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
QString WrapFromScheduled(const QString &text);
|
||||
|
||||
} // namespace Notifications
|
||||
|
||||
2
Telegram/ThirdParty/libtgvoip
vendored
2
Telegram/ThirdParty/libtgvoip
vendored
Submodule Telegram/ThirdParty/libtgvoip updated: 37d98e984f...13a5fcb16b
2
Telegram/ThirdParty/tgcalls
vendored
2
Telegram/ThirdParty/tgcalls
vendored
Submodule Telegram/ThirdParty/tgcalls updated: 6e8b3f7e5f...bc56b9108a
@@ -1,12 +1,14 @@
|
||||
FROM centos:7 AS builder
|
||||
|
||||
ENV GIT https://github.com
|
||||
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
|
||||
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/usr/local/share/pkgconfig
|
||||
ENV QT 5_15_2
|
||||
ENV QT_TAG v5.15.2
|
||||
ENV QT_PREFIX /usr/local/desktop-app/Qt-5.15.2
|
||||
ENV OPENSSL_VER 1_1_1
|
||||
ENV OPENSSL_PREFIX /usr/local/desktop-app/openssl-1.1.1
|
||||
ENV PATH ${PATH}:${QT_PREFIX}/bin
|
||||
ENV Qt5_DIR ${QT_PREFIX}
|
||||
|
||||
RUN yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
|
||||
RUN yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm
|
||||
@@ -27,8 +29,20 @@ ENV LibrariesPath /usr/src/Libraries
|
||||
WORKDIR $LibrariesPath
|
||||
|
||||
FROM builder AS patches
|
||||
RUN git clone $GIT/desktop-app/patches.git
|
||||
RUN cd patches && git checkout 6afd91a
|
||||
ADD https://api.github.com/repos/desktop-app/patches/git/refs/heads/master patches-version.json
|
||||
RUN git clone --depth=1 $GIT/desktop-app/patches.git
|
||||
|
||||
FROM builder AS extra-cmake-modules
|
||||
|
||||
RUN git clone -b v5.77.0 --depth=1 $GIT/KDE/extra-cmake-modules.git
|
||||
|
||||
WORKDIR extra-cmake-modules
|
||||
RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF
|
||||
RUN cmake3 --build build -j$(nproc)
|
||||
RUN DESTDIR="$LibrariesPath/extra-cmake-modules-cache" cmake3 --install build
|
||||
|
||||
WORKDIR ..
|
||||
RUN rm -rf extra-cmake-modules
|
||||
|
||||
FROM builder AS libffi
|
||||
RUN git clone -b v3.3 --depth=1 $GIT/libffi/libffi.git
|
||||
@@ -107,20 +121,18 @@ RUN rm -rf libxcb
|
||||
|
||||
FROM builder AS xcb-wm
|
||||
|
||||
RUN git clone --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-wm.git
|
||||
RUN git clone -b 0.4.1 --depth=1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-wm.git
|
||||
|
||||
WORKDIR libxcb-wm
|
||||
RUN git checkout 0.4.1
|
||||
RUN ./autogen.sh --enable-static
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/xcb-wm-cache" install
|
||||
|
||||
FROM builder AS xcb-util
|
||||
|
||||
RUN git clone --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-util.git
|
||||
RUN git clone -b 0.4.0 --depth=1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-util.git
|
||||
|
||||
WORKDIR libxcb-util
|
||||
RUN git checkout 0.4.0
|
||||
RUN ./autogen.sh --enable-static
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/xcb-util-cache" install
|
||||
@@ -128,30 +140,27 @@ RUN make DESTDIR="$LibrariesPath/xcb-util-cache" install
|
||||
FROM builder AS xcb-image
|
||||
COPY --from=xcb-util ${LibrariesPath}/xcb-util-cache /
|
||||
|
||||
RUN git clone --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-image.git
|
||||
RUN git clone -b 0.4.0 --depth=1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-image.git
|
||||
|
||||
WORKDIR libxcb-image
|
||||
RUN git checkout 0.4.0
|
||||
RUN ./autogen.sh --enable-static
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/xcb-image-cache" install
|
||||
|
||||
FROM builder AS xcb-keysyms
|
||||
|
||||
RUN git clone --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms.git
|
||||
RUN git clone -b 0.4.0 --depth=1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-keysyms.git
|
||||
|
||||
WORKDIR libxcb-keysyms
|
||||
RUN git checkout 0.4.0
|
||||
RUN ./autogen.sh --enable-static
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/xcb-keysyms-cache" install
|
||||
|
||||
FROM builder AS xcb-render-util
|
||||
|
||||
RUN git clone --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util.git
|
||||
RUN git clone -b 0.3.9 --depth=1 --recursive https://gitlab.freedesktop.org/xorg/lib/libxcb-render-util.git
|
||||
|
||||
WORKDIR libxcb-render-util
|
||||
RUN git checkout 0.3.9
|
||||
RUN ./autogen.sh --enable-static
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/xcb-render-util-cache" install
|
||||
@@ -208,6 +217,32 @@ RUN make DESTDIR="$LibrariesPath/wayland-cache" install
|
||||
WORKDIR ..
|
||||
RUN rm -rf wayland
|
||||
|
||||
FROM builder AS wayland-protocols
|
||||
COPY --from=wayland ${LibrariesPath}/wayland-cache /
|
||||
|
||||
RUN git clone -b 1.18 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols.git
|
||||
|
||||
WORKDIR wayland-protocols
|
||||
RUN ./autogen.sh
|
||||
RUN make -j$(nproc)
|
||||
RUN make DESTDIR="$LibrariesPath/wayland-protocols-cache" install
|
||||
|
||||
WORKDIR ..
|
||||
RUN rm -rf wayland-protocols
|
||||
|
||||
FROM builder AS plasma-wayland-protocols
|
||||
COPY --from=extra-cmake-modules ${LibrariesPath}/extra-cmake-modules-cache /
|
||||
|
||||
RUN git clone -b v1.1.1 --depth=1 $GIT/KDE/plasma-wayland-protocols.git
|
||||
|
||||
WORKDIR plasma-wayland-protocols
|
||||
RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release
|
||||
RUN cmake3 --build build -j$(nproc)
|
||||
RUN DESTDIR="$LibrariesPath/plasma-wayland-protocols-cache" cmake3 --install build
|
||||
|
||||
WORKDIR ..
|
||||
RUN rm -rf plasma-wayland-protocols
|
||||
|
||||
FROM builder AS libva
|
||||
|
||||
COPY --from=libffi ${LibrariesPath}/libffi-cache /
|
||||
@@ -457,6 +492,34 @@ RUN make INSTALL_ROOT="$LibrariesPath/qt-cache" install
|
||||
WORKDIR ..
|
||||
RUN rm -rf qt_${QT}
|
||||
|
||||
FROM builder AS kwayland
|
||||
|
||||
COPY --from=extra-cmake-modules ${LibrariesPath}/extra-cmake-modules-cache /
|
||||
COPY --from=libffi ${LibrariesPath}/libffi-cache /
|
||||
COPY --from=mozjpeg ${LibrariesPath}/mozjpeg-cache /
|
||||
COPY --from=xcb ${LibrariesPath}/xcb-cache /
|
||||
COPY --from=xcb-wm ${LibrariesPath}/xcb-wm-cache /
|
||||
COPY --from=xcb-util ${LibrariesPath}/xcb-util-cache /
|
||||
COPY --from=xcb-image ${LibrariesPath}/xcb-image-cache /
|
||||
COPY --from=xcb-keysyms ${LibrariesPath}/xcb-keysyms-cache /
|
||||
COPY --from=xcb-render-util ${LibrariesPath}/xcb-render-util-cache /
|
||||
COPY --from=wayland ${LibrariesPath}/wayland-cache /
|
||||
COPY --from=wayland-protocols ${LibrariesPath}/wayland-protocols-cache /
|
||||
COPY --from=plasma-wayland-protocols ${LibrariesPath}/plasma-wayland-protocols-cache /
|
||||
COPY --from=openssl ${LibrariesPath}/openssl-cache /
|
||||
COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache /
|
||||
COPY --from=qt ${LibrariesPath}/qt-cache /
|
||||
|
||||
RUN git clone -b v5.77.0 --depth=1 $GIT/KDE/kwayland.git
|
||||
|
||||
WORKDIR kwayland
|
||||
RUN cmake3 -B build . -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF
|
||||
RUN cmake3 --build build -j$(nproc)
|
||||
RUN DESTDIR="$LibrariesPath/kwayland-cache" cmake3 --install build
|
||||
|
||||
WORKDIR ..
|
||||
RUN rm -rf kwayland
|
||||
|
||||
FROM patches AS breakpad
|
||||
RUN git clone https://chromium.googlesource.com/breakpad/breakpad.git
|
||||
|
||||
@@ -482,7 +545,7 @@ RUN make DESTDIR="$BreakpadCache" install
|
||||
|
||||
WORKDIR src
|
||||
RUN rm -rf testing
|
||||
RUN git clone $GIT/google/googletest.git testing
|
||||
RUN git clone --depth=1 $GIT/google/googletest.git testing
|
||||
|
||||
WORKDIR tools
|
||||
RUN sed -i 's/minidump_upload.m/minidump_upload.cc/' linux/tools_linux.gypi
|
||||
@@ -503,10 +566,10 @@ COPY --from=opus ${LibrariesPath}/opus-cache /
|
||||
COPY --from=ffmpeg ${LibrariesPath}/ffmpeg-cache /
|
||||
COPY --from=openssl ${LibrariesPath}/openssl-cache /
|
||||
|
||||
RUN git clone --recursive $GIT/desktop-app/tg_owt.git
|
||||
ADD https://api.github.com/repos/desktop-app/tg_owt/git/refs/heads/master tg_owt-version.json
|
||||
RUN git clone --depth=1 --recursive $GIT/desktop-app/tg_owt.git
|
||||
|
||||
WORKDIR tg_owt
|
||||
RUN git checkout 75ac669
|
||||
|
||||
RUN cmake3 -B out/Release . \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
@@ -552,6 +615,7 @@ COPY --from=openal ${LibrariesPath}/openal-cache /
|
||||
COPY --from=openssl ${LibrariesPath}/openssl-cache /
|
||||
COPY --from=xkbcommon ${LibrariesPath}/xkbcommon-cache /
|
||||
COPY --from=qt ${LibrariesPath}/qt-cache /
|
||||
COPY --from=kwayland ${LibrariesPath}/kwayland-cache /
|
||||
COPY --from=breakpad ${LibrariesPath}/breakpad breakpad
|
||||
COPY --from=breakpad ${LibrariesPath}/breakpad-cache /
|
||||
COPY --from=webrtc ${LibrariesPath}/tg_owt tg_owt
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
AppVersion 2005003
|
||||
AppVersion 2005004
|
||||
AppVersionStrMajor 2.5
|
||||
AppVersionStrSmall 2.5.3
|
||||
AppVersionStr 2.5.3
|
||||
AppVersionStrSmall 2.5.4
|
||||
AppVersionStr 2.5.4
|
||||
BetaChannel 1
|
||||
AlphaVersion 0
|
||||
AppVersionOriginal 2.5.3.beta
|
||||
AppVersionOriginal 2.5.4.beta
|
||||
|
||||
Submodule Telegram/lib_ui updated: b5fb343d6c...9ebd51c8f8
Submodule Telegram/lib_webrtc updated: d9e8307af6...c41c510b29
@@ -1,3 +1,10 @@
|
||||
2.5.4 beta (07.01.21)
|
||||
|
||||
- Implement new audio module code for calls and voice chats.
|
||||
- Allow retracting votes from polls in comments to channel posts.
|
||||
- Show small voice chat button for empty voice chats.
|
||||
- Fix media viewer updating when screen resolution is changed.
|
||||
|
||||
2.5.3 beta (30.12.20)
|
||||
|
||||
- Allow using mouse buttons in Push-to-Talk shortcut.
|
||||
|
||||
2
cmake
2
cmake
Submodule cmake updated: 2208358765...561273a2f8
@@ -68,17 +68,8 @@ Go to ***BuildPath*** and run
|
||||
cd build
|
||||
CFLAGS="$UNGUARDED" CPPFLAGS="$UNGUARDED" cmake -D CMAKE_OSX_DEPLOYMENT_TARGET:STRING=10.12 -D CMAKE_INSTALL_PREFIX:STRING=/usr/local/macos ..
|
||||
make $MAKE_THREADS_CNT
|
||||
cd ../..
|
||||
|
||||
xz_ver=5.2.4
|
||||
wget https://tukaani.org/xz/xz-$xz_ver.tar.gz
|
||||
tar -xvzf xz-$xz_ver.tar.gz
|
||||
rm xz-$xz_ver.tar.gz
|
||||
cd xz-$xz_ver
|
||||
CFLAGS="$MIN_VER" LDFLAGS="$MIN_VER" ./configure --prefix=/usr/local/macos
|
||||
make $MAKE_THREADS_CNT
|
||||
sudo make install
|
||||
cd ..
|
||||
cd ../..
|
||||
|
||||
git clone https://github.com/desktop-app/zlib.git
|
||||
cd zlib
|
||||
|
||||
@@ -74,6 +74,7 @@ parts:
|
||||
- libasound2-dev
|
||||
- libglib2.0-dev
|
||||
- libgtk-3-dev
|
||||
- libkf5wayland-dev
|
||||
- liblzma-dev
|
||||
- libopus-dev
|
||||
- libpulse-dev
|
||||
@@ -90,6 +91,7 @@ parts:
|
||||
- libasound2
|
||||
- libglib2.0-0
|
||||
- libgtk-3-0
|
||||
- libkf5waylandclient5
|
||||
- liblzma5
|
||||
- libopus0
|
||||
- libpulse0
|
||||
@@ -251,7 +253,7 @@ parts:
|
||||
webrtc:
|
||||
source: https://github.com/desktop-app/tg_owt.git
|
||||
source-depth: 1
|
||||
source-commit: 75ac66937341d8a9207375aaee79b4bdc500146c
|
||||
source-commit: d91d618889cc743aafd809151449012de62e5327
|
||||
plugin: cmake
|
||||
build-packages:
|
||||
- yasm
|
||||
|
||||
Reference in New Issue
Block a user