From dbb0030893c0b559c777aa26ca108caa8c705c60 Mon Sep 17 00:00:00 2001 From: Vitaly Zaitsev <vitaly@easycoding.org> Date: Sun, 18 Mar 2018 17:24:43 +0100 Subject: [PATCH] Completely drop GTK dialogs. Use native instead. Also this commit will remove libnotify support. Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org> --- Telegram/CMakeLists.txt | 2 +- .../platform/linux/file_utilities_linux.cpp | 513 ----------------- .../platform/linux/file_utilities_linux.h | 113 ---- .../platform/linux/linux_gdk_helper.cpp | 95 ---- .../platform/linux/linux_gdk_helper.h | 18 - .../platform/linux/linux_libnotify.cpp | 76 --- .../platform/linux/linux_libnotify.h | 112 ---- .../SourceFiles/platform/linux/linux_libs.cpp | 250 --------- .../SourceFiles/platform/linux/linux_libs.h | 331 ----------- .../platform/linux/main_window_linux.cpp | 312 +---------- .../linux/notifications_manager_linux.cpp | 518 ------------------ 11 files changed, 5 insertions(+), 2335 deletions(-) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 65c56b647..0559cd32e 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -592,7 +592,7 @@ add_definitions(-DAL_ALEXT_PROTOTYPES) add_definitions(-DTGVOIP_USE_CXX11_LIB) add_definitions(-DTDESKTOP_DISABLE_CRASH_REPORTS) -add_definitions(-DTDESKTOP_DISABLE_GTK_INTEGRATION) # Linux only +add_definitions(-DTDESKTOP_DISABLE_UNITY_INTEGRATION) # Linux only if (LINUX) add_definitions(-D_REENTRANT) diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp index f847f3141..b5622aded 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.cpp @@ -95,222 +95,15 @@ void UnsafeShowInFolder(const QString &filepath) { namespace FileDialog { namespace { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - -// GTK file chooser image preview: thanks to Chromium - -// The size of the preview we display for selected image files. We set height -// larger than width because generally there is more free space vertically -// than horiztonally (setting the preview image will alway expand the width of -// the dialog, but usually not the height). The image's aspect ratio will always -// be preserved. -constexpr auto kPreviewWidth = 256; -constexpr auto kPreviewHeight = 512; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION using Type = ::FileDialog::internal::Type; -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -bool NativeSupported() { - return Platform::internal::GdkHelperLoaded() - && (Libs::gtk_widget_hide_on_delete != nullptr) - && (Libs::gtk_clipboard_store != nullptr) - && (Libs::gtk_clipboard_get != nullptr) - && (Libs::gtk_widget_destroy != nullptr) - && (Libs::gtk_dialog_get_type != nullptr) - && (Libs::gtk_dialog_run != nullptr) - && (Libs::gtk_widget_realize != nullptr) - && (Libs::gdk_window_set_modal_hint != nullptr) - && (Libs::gtk_widget_show != nullptr) - && (Libs::gdk_window_focus != nullptr) - && (Libs::gtk_widget_hide != nullptr) - && (Libs::gtk_widget_hide_on_delete != nullptr) - && (Libs::gtk_file_chooser_dialog_new != nullptr) - && (Libs::gtk_file_chooser_get_type != nullptr) - && (Libs::gtk_file_chooser_set_current_folder != nullptr) - && (Libs::gtk_file_chooser_get_current_folder != nullptr) - && (Libs::gtk_file_chooser_set_current_name != nullptr) - && (Libs::gtk_file_chooser_select_filename != nullptr) - && (Libs::gtk_file_chooser_get_filenames != nullptr) - && (Libs::gtk_file_chooser_set_filter != nullptr) - && (Libs::gtk_file_chooser_get_filter != nullptr) - && (Libs::gtk_window_get_type != nullptr) - && (Libs::gtk_window_set_title != nullptr) - && (Libs::gtk_file_chooser_set_local_only != nullptr) - && (Libs::gtk_file_chooser_set_action != nullptr) - && (Libs::gtk_file_chooser_set_select_multiple != nullptr) - && (Libs::gtk_file_chooser_set_do_overwrite_confirmation != nullptr) - && (Libs::gtk_file_chooser_remove_filter != nullptr) - && (Libs::gtk_file_filter_set_name != nullptr) - && (Libs::gtk_file_filter_add_pattern != nullptr) - && (Libs::gtk_file_chooser_add_filter != nullptr) - && (Libs::gtk_file_filter_new != nullptr); -} - -bool PreviewSupported() { - return NativeSupported() - && (Libs::gdk_pixbuf_new_from_file_at_size != nullptr); -} - -bool GetNative(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) { - auto parent = Messenger::Instance().getFileDialogParent(); - internal::GtkFileDialog dialog(parent, caption, QString(), filter); - - dialog.setModal(true); - if (type == Type::ReadFile || type == Type::ReadFiles) { - dialog.setFileMode((type == Type::ReadFiles) ? QFileDialog::ExistingFiles : QFileDialog::ExistingFile); - dialog.setAcceptMode(QFileDialog::AcceptOpen); - } else if (type == Type::ReadFolder) { - dialog.setAcceptMode(QFileDialog::AcceptOpen); - dialog.setFileMode(QFileDialog::Directory); - dialog.setOption(QFileDialog::ShowDirsOnly); - } else { - dialog.setFileMode(QFileDialog::AnyFile); - dialog.setAcceptMode(QFileDialog::AcceptSave); - } - if (startFile.isEmpty() || startFile.at(0) != '/') { - startFile = cDialogLastPath() + '/' + startFile; - } - dialog.selectFile(startFile); - - int res = dialog.exec(); - - QString path = dialog.directory().absolutePath(); - if (path != cDialogLastPath()) { - cSetDialogLastPath(path); - Local::writeUserSettings(); - } - - if (res == QDialog::Accepted) { - if (type == Type::ReadFiles) { - files = dialog.selectedFiles(); - } else { - files = dialog.selectedFiles().mid(0, 1); - } - return true; - } - - files = QStringList(); - remoteContent = QByteArray(); - return false; -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - } // namespace bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (NativeSupported()) { - return GetNative(files, remoteContent, caption, filter, type, startFile); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION return ::FileDialog::internal::GetDefault(files, remoteContent, caption, filter, type, startFile); } -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -namespace internal { - -QGtkDialog::QGtkDialog(GtkWidget *gtkWidget) : gtkWidget(gtkWidget) { - Libs::g_signal_connect_swapped_helper(Libs::g_object_cast(gtkWidget), "response", GCallback(onResponse), this); - Libs::g_signal_connect_helper(Libs::g_object_cast(gtkWidget), "delete-event", GCallback(Libs::gtk_widget_hide_on_delete), nullptr); - if (PreviewSupported()) { - _preview = Libs::gtk_image_new(); - Libs::g_signal_connect_swapped_helper(Libs::g_object_cast(gtkWidget), "update-preview", GCallback(onUpdatePreview), this); - Libs::gtk_file_chooser_set_preview_widget(Libs::gtk_file_chooser_cast(gtkWidget), _preview); - } -} - -QGtkDialog::~QGtkDialog() { - Libs::gtk_clipboard_store(Libs::gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)); - Libs::gtk_widget_destroy(gtkWidget); -} - -GtkDialog *QGtkDialog::gtkDialog() const { - return Libs::gtk_dialog_cast(gtkWidget); -} - -void QGtkDialog::exec() { - if (auto w = App::wnd()) { - w->reActivateWindow(); - } - if (modality() == Qt::ApplicationModal) { - // block input to the whole app, including other GTK dialogs - Libs::gtk_dialog_run(gtkDialog()); - } else { - // block input to the window, allow input to other GTK dialogs - QEventLoop loop; - connect(this, SIGNAL(accept()), &loop, SLOT(quit())); - connect(this, SIGNAL(reject()), &loop, SLOT(quit())); - loop.exec(); - } -} - -void QGtkDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { - connect(parent, &QWindow::destroyed, this, &QGtkDialog::onParentWindowDestroyed, - Qt::UniqueConnection); - setParent(parent); - setFlags(flags); - setModality(modality); - - Libs::gtk_widget_realize(gtkWidget); // creates X window - - if (parent) { - Platform::internal::XSetTransientForHint(Libs::gtk_widget_get_window(gtkWidget), parent->winId()); - } - - if (modality != Qt::NonModal) { - Libs::gdk_window_set_modal_hint(Libs::gtk_widget_get_window(gtkWidget), true); - QGuiApplicationPrivate::showModalWindow(this); - } - - Libs::gtk_widget_show(gtkWidget); - Libs::gdk_window_focus(Libs::gtk_widget_get_window(gtkWidget), 0); -} - -void QGtkDialog::hide() { - QGuiApplicationPrivate::hideModalWindow(this); - Libs::gtk_widget_hide(gtkWidget); -} - -void QGtkDialog::onResponse(QGtkDialog *dialog, int response) { - if (response == GTK_RESPONSE_OK) - emit dialog->accept(); - else - emit dialog->reject(); -} - -void QGtkDialog::onUpdatePreview(QGtkDialog* dialog) { - auto filename = Libs::gtk_file_chooser_get_preview_filename(Libs::gtk_file_chooser_cast(dialog->gtkWidget)); - if (!filename) { - Libs::gtk_file_chooser_set_preview_widget_active(Libs::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)) { - Libs::g_free(filename); - Libs::gtk_file_chooser_set_preview_widget_active(Libs::gtk_file_chooser_cast(dialog->gtkWidget), false); - return; - } - - // This will preserve the image's aspect ratio. - auto pixbuf = Libs::gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, kPreviewHeight, nullptr); - Libs::g_free(filename); - if (pixbuf) { - Libs::gtk_image_set_from_pixbuf(Libs::gtk_image_cast(dialog->_preview), pixbuf); - Libs::g_object_unref(pixbuf); - } - Libs::gtk_file_chooser_set_preview_widget_active(Libs::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); -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - namespace { const char *filterRegExp = @@ -328,311 +121,5 @@ QStringList cleanFilterList(const QString &filter) { } } // namespace - -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -GtkFileDialog::GtkFileDialog(QWidget *parent, const QString &caption, const QString &directory, const QString &filter) : QDialog(parent) -, _windowTitle(caption) -, _initialDirectory(directory) { - auto filters = qt_make_filter_list(filter); - const int numFilters = filters.count(); - _nameFilters.reserve(numFilters); - for (int i = 0; i < numFilters; ++i) { - _nameFilters << filters[i].simplified(); - } - - d.reset(new QGtkDialog(Libs::gtk_file_chooser_dialog_new("", nullptr, - GTK_FILE_CHOOSER_ACTION_OPEN, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_OK, GTK_RESPONSE_OK, NULL))); - connect(d.data(), SIGNAL(accept()), this, SLOT(onAccepted())); - connect(d.data(), SIGNAL(reject()), this, SLOT(onRejected())); - - Libs::g_signal_connect_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "selection-changed", G_CALLBACK(onSelectionChanged), this); - Libs::g_signal_connect_swapped_helper(Libs::gtk_file_chooser_cast(d->gtkDialog()), "current-folder-changed", G_CALLBACK(onCurrentFolderChanged), this); -} - -GtkFileDialog::~GtkFileDialog() { -} - -void GtkFileDialog::showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) { - _dir.clear(); - _selection.clear(); - - applyOptions(); - return d->show(flags, modality, parent); -} - -void GtkFileDialog::setVisible(bool visible) { - if (visible) { - if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) { - return; - } - } else if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden)) { - return; - } - - if (visible) { - showHelper(windowFlags(), windowModality(), parentWidget() ? parentWidget()->windowHandle() : nullptr); - } else { - hideHelper(); - } - - // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below - // updates the state correctly, but skips showing the non-native version: - setAttribute(Qt::WA_DontShowOnScreen); - - QDialog::setVisible(visible); -} - -int GtkFileDialog::exec() { - d->setModality(windowModality()); - - bool deleteOnClose = testAttribute(Qt::WA_DeleteOnClose); - setAttribute(Qt::WA_DeleteOnClose, false); - - bool wasShowModal = testAttribute(Qt::WA_ShowModal); - setAttribute(Qt::WA_ShowModal, true); - setResult(0); - - show(); - - QPointer<QDialog> guard = this; - d->exec(); - if (guard.isNull()) - return QDialog::Rejected; - - setAttribute(Qt::WA_ShowModal, wasShowModal); - - return result(); -} - -void GtkFileDialog::hideHelper() { - // After GtkFileChooserDialog has been hidden, gtk_file_chooser_get_current_folder() - // & gtk_file_chooser_get_filenames() will return bogus values -> cache the actual - // values before hiding the dialog - _dir = directory().absolutePath(); - _selection = selectedFiles(); - - d->hide(); -} - -bool GtkFileDialog::defaultNameFilterDisables() const { - return false; -} - -void GtkFileDialog::setDirectory(const QString &directory) { - GtkDialog *gtkDialog = d->gtkDialog(); - Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), directory.toUtf8()); -} - -QDir GtkFileDialog::directory() const { - // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_current_folder() - // returns a bogus value -> return the cached value before hiding - if (!_dir.isEmpty()) - return _dir; - - QString ret; - GtkDialog *gtkDialog = d->gtkDialog(); - gchar *folder = Libs::gtk_file_chooser_get_current_folder(Libs::gtk_file_chooser_cast(gtkDialog)); - if (folder) { - ret = QString::fromUtf8(folder); - Libs::g_free(folder); - } - return QDir(ret); -} - -void GtkFileDialog::selectFile(const QString &filename) { - _initialFiles.clear(); - _initialFiles.append(filename); -} - -QStringList GtkFileDialog::selectedFiles() const { - // While GtkFileChooserDialog is hidden, gtk_file_chooser_get_filenames() - // returns a bogus value -> return the cached value before hiding - if (!_selection.isEmpty()) - return _selection; - - QStringList selection; - GtkDialog *gtkDialog = d->gtkDialog(); - GSList *filenames = Libs::gtk_file_chooser_get_filenames(Libs::gtk_file_chooser_cast(gtkDialog)); - for (GSList *it = filenames; it; it = it->next) - selection += QString::fromUtf8((const char*)it->data); - Libs::g_slist_free(filenames); - return selection; -} - -void GtkFileDialog::setFilter() { - applyOptions(); -} - -void GtkFileDialog::selectNameFilter(const QString &filter) { - GtkFileFilter *gtkFilter = _filters.value(filter); - if (gtkFilter) { - GtkDialog *gtkDialog = d->gtkDialog(); - Libs::gtk_file_chooser_set_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); - } -} - -QString GtkFileDialog::selectedNameFilter() const { - GtkDialog *gtkDialog = d->gtkDialog(); - GtkFileFilter *gtkFilter = Libs::gtk_file_chooser_get_filter(Libs::gtk_file_chooser_cast(gtkDialog)); - return _filterNames.value(gtkFilter); -} - -void GtkFileDialog::onAccepted() { - emit accept(); - -// QString filter = selectedNameFilter(); -// if (filter.isEmpty()) -// emit filterSelected(filter); - -// QList<QUrl> files = selectedFiles(); -// emit filesSelected(files); -// if (files.count() == 1) -// emit fileSelected(files.first()); -} - -void GtkFileDialog::onRejected() { - emit reject(); - -// -} - -void GtkFileDialog::onSelectionChanged(GtkDialog *gtkDialog, GtkFileDialog *helper) { -// QString selection; -// gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(gtkDialog)); -// if (filename) { -// selection = QString::fromUtf8(filename); -// g_free(filename); -// } -// emit helper->currentChanged(QUrl::fromLocalFile(selection)); -} - -void GtkFileDialog::onCurrentFolderChanged(GtkFileDialog *dialog) { -// emit dialog->directoryEntered(dialog->directory()); -} - -GtkFileChooserAction gtkFileChooserAction(QFileDialog::FileMode fileMode, QFileDialog::AcceptMode acceptMode) { - switch (fileMode) { - case QFileDialog::AnyFile: - case QFileDialog::ExistingFile: - case QFileDialog::ExistingFiles: - if (acceptMode == QFileDialog::AcceptOpen) - return GTK_FILE_CHOOSER_ACTION_OPEN; - else - return GTK_FILE_CHOOSER_ACTION_SAVE; - case QFileDialog::Directory: - case QFileDialog::DirectoryOnly: - default: - if (acceptMode == QFileDialog::AcceptOpen) - return GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; - else - return GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER; - } -} - -bool CustomButtonsSupported() { - return (Libs::gtk_dialog_get_widget_for_response != nullptr) - && (Libs::gtk_button_set_label != nullptr) - && (Libs::gtk_button_get_type != nullptr); -} - -void GtkFileDialog::applyOptions() { - GtkDialog *gtkDialog = d->gtkDialog(); - - Libs::gtk_window_set_title(Libs::gtk_window_cast(gtkDialog), _windowTitle.toUtf8()); - Libs::gtk_file_chooser_set_local_only(Libs::gtk_file_chooser_cast(gtkDialog), true); - - const GtkFileChooserAction action = gtkFileChooserAction(_fileMode, _acceptMode); - Libs::gtk_file_chooser_set_action(Libs::gtk_file_chooser_cast(gtkDialog), action); - - const bool selectMultiple = (_fileMode == QFileDialog::ExistingFiles); - Libs::gtk_file_chooser_set_select_multiple(Libs::gtk_file_chooser_cast(gtkDialog), selectMultiple); - - const bool confirmOverwrite = !_options.testFlag(QFileDialog::DontConfirmOverwrite); - Libs::gtk_file_chooser_set_do_overwrite_confirmation(Libs::gtk_file_chooser_cast(gtkDialog), confirmOverwrite); - - if (!_nameFilters.isEmpty()) - setNameFilters(_nameFilters); - - if (!_initialDirectory.isEmpty()) - setDirectory(_initialDirectory); - - for_const (const auto &filename, _initialFiles) { - if (_acceptMode == QFileDialog::AcceptSave) { - QFileInfo fi(filename); - Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), fi.path().toUtf8()); - Libs::gtk_file_chooser_set_current_name(Libs::gtk_file_chooser_cast(gtkDialog), fi.fileName().toUtf8()); - } else if (filename.endsWith('/')) { - Libs::gtk_file_chooser_set_current_folder(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); - } else { - Libs::gtk_file_chooser_select_filename(Libs::gtk_file_chooser_cast(gtkDialog), filename.toUtf8()); - } - } - - const QString initialNameFilter = _nameFilters.isEmpty() ? QString() : _nameFilters.front(); - if (!initialNameFilter.isEmpty()) - selectNameFilter(initialNameFilter); - - if (CustomButtonsSupported()) { - GtkWidget *acceptButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_OK); - if (acceptButton) { - /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Accept)) - Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), opts->labelText(QFileDialogOptions::Accept).toUtf8()); - else*/ if (_acceptMode == QFileDialog::AcceptOpen) - Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_OPEN); - else - Libs::gtk_button_set_label(Libs::gtk_button_cast(acceptButton), GTK_STOCK_SAVE); - } - - GtkWidget *rejectButton = Libs::gtk_dialog_get_widget_for_response(gtkDialog, GTK_RESPONSE_CANCEL); - if (rejectButton) { - /*if (opts->isLabelExplicitlySet(QFileDialogOptions::Reject)) - Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), opts->labelText(QFileDialogOptions::Reject).toUtf8()); - else*/ - Libs::gtk_button_set_label(Libs::gtk_button_cast(rejectButton), GTK_STOCK_CANCEL); - } - } -} - -void GtkFileDialog::setNameFilters(const QStringList &filters) { - GtkDialog *gtkDialog = d->gtkDialog(); - foreach (GtkFileFilter *filter, _filters) - Libs::gtk_file_chooser_remove_filter(Libs::gtk_file_chooser_cast(gtkDialog), filter); - - _filters.clear(); - _filterNames.clear(); - - for_const (auto &filter, filters) { - GtkFileFilter *gtkFilter = Libs::gtk_file_filter_new(); - auto name = filter;//.left(filter.indexOf(QLatin1Char('('))); - auto extensions = cleanFilterList(filter); - - Libs::gtk_file_filter_set_name(gtkFilter, name.isEmpty() ? extensions.join(QStringLiteral(", ")).toUtf8() : name.toUtf8()); - for_const (auto &ext, extensions) { - auto caseInsensitiveExt = QString(); - caseInsensitiveExt.reserve(4 * ext.size()); - for_const (auto ch, ext) { - auto chLower = ch.toLower(); - auto chUpper = ch.toUpper(); - if (chLower != chUpper) { - caseInsensitiveExt.append('[').append(chLower).append(chUpper).append(']'); - } else { - caseInsensitiveExt.append(ch); - } - } - - Libs::gtk_file_filter_add_pattern(gtkFilter, caseInsensitiveExt.toUtf8()); - } - - Libs::gtk_file_chooser_add_filter(Libs::gtk_file_chooser_cast(gtkDialog), gtkFilter); - - _filters.insert(filter, gtkFilter); - _filterNames.insert(gtkFilter, filter); - } -} - -} // namespace internal -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } // namespace FileDialog } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/file_utilities_linux.h b/Telegram/SourceFiles/platform/linux/file_utilities_linux.h index 16ca45a3e..4139b76a3 100644 --- a/Telegram/SourceFiles/platform/linux/file_utilities_linux.h +++ b/Telegram/SourceFiles/platform/linux/file_utilities_linux.h @@ -24,10 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org extern "C" { #undef signals -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION #define signals public } // extern "C" @@ -70,114 +66,5 @@ inline void InitLastPath() { ::FileDialog::internal::InitLastPathDefault(); } -namespace internal { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - -// This is a patched copy of qgtk2 theme plugin. -// We need to use our own gtk file dialog instead of -// styling Qt file dialog, because Qt only works with gtk2. -// We need to be able to work with gtk2 and gtk3, because -// we use gtk3 to work with appindicator3. -class QGtkDialog : public QWindow { - Q_OBJECT - -public: - QGtkDialog(GtkWidget *gtkWidget); - ~QGtkDialog(); - - GtkDialog *gtkDialog() const; - - void exec(); - void show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); - void hide(); - -signals: - void accept(); - void reject(); - -protected: - static void onResponse(QGtkDialog *dialog, int response); - static void onUpdatePreview(QGtkDialog *dialog); - -private slots: - void onParentWindowDestroyed(); - -private: - GtkWidget *gtkWidget; - GtkWidget *_preview = nullptr; - -}; - -class GtkFileDialog : public QDialog { - Q_OBJECT - -public: - GtkFileDialog(QWidget *parent = Q_NULLPTR, - const QString &caption = QString(), - const QString &directory = QString(), - const QString &filter = QString()); - ~GtkFileDialog(); - - void setVisible(bool visible) override; - - void setWindowTitle(const QString &windowTitle) { - _windowTitle = windowTitle; - } - void setAcceptMode(QFileDialog::AcceptMode acceptMode) { - _acceptMode = acceptMode; - } - void setFileMode(QFileDialog::FileMode fileMode) { - _fileMode = fileMode; - } - void setOption(QFileDialog::Option option, bool on = true) { - if (on) { - _options |= option; - } else { - _options &= ~option; - } - } - - int exec() override; - - bool defaultNameFilterDisables() const; - void setDirectory(const QString &directory); - QDir directory() const; - void selectFile(const QString &filename); - QStringList selectedFiles() const; - void setFilter(); - void selectNameFilter(const QString &filter); - QString selectedNameFilter() const; - -private slots: - void onAccepted(); - void onRejected(); - -private: - static void onSelectionChanged(GtkDialog *dialog, GtkFileDialog *helper); - static void onCurrentFolderChanged(GtkFileDialog *helper); - void applyOptions(); - void setNameFilters(const QStringList &filters); - - void showHelper(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent); - void hideHelper(); - - // Options - QFileDialog::Options _options = { 0 }; - QString _windowTitle = "Choose file"; - QString _initialDirectory; - QStringList _initialFiles; - QStringList _nameFilters; - QFileDialog::AcceptMode _acceptMode = QFileDialog::AcceptOpen; - QFileDialog::FileMode _fileMode = QFileDialog::ExistingFile; - - QString _dir; - QStringList _selection; - QHash<QString, GtkFileFilter*> _filters; - QHash<GtkFileFilter*, QString> _filterNames; - QScopedPointer<QGtkDialog> d; -}; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - -} // namespace internal } // namespace FileDialog } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp index 82232fb76..2aa4f28bf 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.cpp @@ -18,98 +18,3 @@ to link the code of portions of this program with the OpenSSL library. Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -#include "platform/linux/linux_gdk_helper.h" - -#include "platform/linux/linux_libs.h" - -extern "C" { -#undef signals -#include <gdk/gdkx.h> -#define signals public -} // extern "C" - -namespace Platform { -namespace internal { - -enum class GtkLoaded { - GtkNone, - Gtk2, - Gtk3, -}; - -GtkLoaded gdk_helper_loaded = GtkLoaded::GtkNone; - -// To be able to compile with gtk-3.0 headers as well -#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; - -// Gtk 3 -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 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; - -bool GdkHelperLoadGtk2(QLibrary &lib) { - if (!Libs::load(lib, "gdk_x11_drawable_get_xdisplay", gdk_x11_drawable_get_xdisplay)) return false; - if (!Libs::load(lib, "gdk_x11_drawable_get_xid", gdk_x11_drawable_get_xid)) return false; - return true; -} - -bool GdkHelperLoadGtk3(QLibrary &lib) { - if (!Libs::load(lib, "gdk_x11_window_get_type", gdk_x11_window_get_type)) return false; - if (!Libs::load(lib, "gdk_window_get_display", gdk_window_get_display)) return false; - if (!Libs::load(lib, "gdk_x11_display_get_xdisplay", gdk_x11_display_get_xdisplay)) return false; - if (!Libs::load(lib, "gdk_x11_window_get_xid", gdk_x11_window_get_xid)) return false; - return true; -} - -void GdkHelperLoad(QLibrary &lib) { - gdk_helper_loaded = GtkLoaded::GtkNone; - if (GdkHelperLoadGtk2(lib)) { - gdk_helper_loaded = GtkLoaded::Gtk2; - } else if (GdkHelperLoadGtk3(lib)) { - gdk_helper_loaded = GtkLoaded::Gtk3; - } -} - -bool GdkHelperLoaded() { - return gdk_helper_loaded != GtkLoaded::GtkNone; -} - -void XSetTransientForHint(GdkWindow *window, quintptr winId) { - if (gdk_helper_loaded == GtkLoaded::Gtk2) { - ::XSetTransientForHint(gdk_x11_drawable_get_xdisplay(window), - gdk_x11_drawable_get_xid(window), - winId); - } else if (gdk_helper_loaded == GtkLoaded::Gtk3) { - 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); - } - } -} - -} // namespace internal -} // namespace Platform -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h index 3fcb72940..e86499c57 100644 --- a/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h +++ b/Telegram/SourceFiles/platform/linux/linux_gdk_helper.h @@ -22,21 +22,3 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include <QtCore/QObject> -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -extern "C" { -#undef signals -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#define signals public -} // extern "C" - -namespace Platform { -namespace internal { - -void GdkHelperLoad(QLibrary &lib); -bool GdkHelperLoaded(); -void XSetTransientForHint(GdkWindow *window, quintptr winId); - -} // namespace internal -} // namespace Platform -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/linux_libnotify.cpp b/Telegram/SourceFiles/platform/linux/linux_libnotify.cpp index 4f969d918..9e69a1224 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libnotify.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_libnotify.cpp @@ -43,81 +43,5 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) { } } // namespace - -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -f_notify_init notify_init = nullptr; -f_notify_uninit notify_uninit = nullptr; -f_notify_is_initted notify_is_initted = nullptr; -//f_notify_get_app_name notify_get_app_name = nullptr; -//f_notify_set_app_name notify_set_app_name = nullptr; -f_notify_get_server_caps notify_get_server_caps = nullptr; -f_notify_get_server_info notify_get_server_info = nullptr; - -f_notify_notification_new notify_notification_new = nullptr; -//f_notify_notification_update notify_notification_update = nullptr; -f_notify_notification_show notify_notification_show = nullptr; -//f_notify_notification_set_app_name notify_notification_set_app_name = nullptr; -f_notify_notification_set_timeout notify_notification_set_timeout = nullptr; -//f_notify_notification_set_category notify_notification_set_category = nullptr; -//f_notify_notification_set_urgency notify_notification_set_urgency = nullptr; -//f_notify_notification_set_icon_from_pixbuf notify_notification_set_icon_from_pixbuf = nullptr; -f_notify_notification_set_image_from_pixbuf notify_notification_set_image_from_pixbuf = nullptr; -//f_notify_notification_set_hint notify_notification_set_hint = nullptr; -//f_notify_notification_set_hint_int32 notify_notification_set_hint_int32 = nullptr; -//f_notify_notification_set_hint_uint32 notify_notification_set_hint_uint32 = nullptr; -//f_notify_notification_set_hint_double notify_notification_set_hint_double = nullptr; -f_notify_notification_set_hint_string notify_notification_set_hint_string = nullptr; -//f_notify_notification_set_hint_byte notify_notification_set_hint_byte = nullptr; -//f_notify_notification_set_hint_byte_array notify_notification_set_hint_byte_array = nullptr; -//f_notify_notification_clear_hints notify_notification_clear_hints = nullptr; -f_notify_notification_add_action notify_notification_add_action = nullptr; -f_notify_notification_clear_actions notify_notification_clear_actions = nullptr; -f_notify_notification_close notify_notification_close = nullptr; -f_notify_notification_get_closed_reason notify_notification_get_closed_reason = nullptr; - -void startLibNotify() { - DEBUG_LOG(("Loading libnotify")); - - QLibrary lib_notify; - if (!loadLibrary(lib_notify, "notify", 4)) { - if (!loadLibrary(lib_notify, "notify", 5)) { - if (!loadLibrary(lib_notify, "notify", 1)) { - return; - } - } - } - - load(lib_notify, "notify_init", notify_init); - load(lib_notify, "notify_uninit", notify_uninit); - load(lib_notify, "notify_is_initted", notify_is_initted); -// load(lib_notify, "notify_get_app_name", notify_get_app_name); -// load(lib_notify, "notify_set_app_name", notify_set_app_name); - load(lib_notify, "notify_get_server_caps", notify_get_server_caps); - load(lib_notify, "notify_get_server_info", notify_get_server_info); - - load(lib_notify, "notify_notification_new", notify_notification_new); -// load(lib_notify, "notify_notification_update", notify_notification_update); - load(lib_notify, "notify_notification_show", notify_notification_show); -// load(lib_notify, "notify_notification_set_app_name", notify_notification_set_app_name); - load(lib_notify, "notify_notification_set_timeout", notify_notification_set_timeout); -// load(lib_notify, "notify_notification_set_category", notify_notification_set_category); -// load(lib_notify, "notify_notification_set_urgency", notify_notification_set_urgency); -// load(lib_notify, "notify_notification_set_icon_from_pixbuf", notify_notification_set_icon_from_pixbuf); - load(lib_notify, "notify_notification_set_image_from_pixbuf", notify_notification_set_image_from_pixbuf); -// load(lib_notify, "notify_notification_set_hint", notify_notification_set_hint); -// load(lib_notify, "notify_notification_set_hint_int32", notify_notification_set_hint_int32); -// load(lib_notify, "notify_notification_set_hint_uint32", notify_notification_set_hint_uint32); -// load(lib_notify, "notify_notification_set_hint_double", notify_notification_set_hint_double); - load(lib_notify, "notify_notification_set_hint_string", notify_notification_set_hint_string); -// load(lib_notify, "notify_notification_set_hint_byte", notify_notification_set_hint_byte); -// load(lib_notify, "notify_notification_set_hint_byte_array", notify_notification_set_hint_byte_array); -// load(lib_notify, "notify_notification_clear_hints", notify_notification_clear_hints); - load(lib_notify, "notify_notification_add_action", notify_notification_add_action); - load(lib_notify, "notify_notification_clear_actions", notify_notification_clear_actions); - load(lib_notify, "notify_notification_close", notify_notification_close); - load(lib_notify, "notify_notification_get_closed_reason", notify_notification_get_closed_reason); -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - } // namespace Libs } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/linux_libnotify.h b/Telegram/SourceFiles/platform/linux/linux_libnotify.h index c23f32432..85af2faec 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libnotify.h +++ b/Telegram/SourceFiles/platform/linux/linux_libnotify.h @@ -19,115 +19,3 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once - -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -extern "C" { -#undef signals -#include <gtk/gtk.h> -#define signals public -} // extern "C" - -namespace Platform { -namespace Libs { - -void startLibNotify(); - -constexpr gint NOTIFY_EXPIRES_DEFAULT = -1; -constexpr gint NOTIFY_EXPIRES_NEVER = 0; - -struct NotifyNotification; -typedef enum { - NOTIFY_URGENCY_LOW, - NOTIFY_URGENCY_NORMAL, - NOTIFY_URGENCY_CRITICAL, -} NotifyUrgency; - -using NotifyActionCallback = void (*)(NotifyNotification *notification, char *action, gpointer user_data); - -using f_notify_init = gboolean (*)(const char *app_name); -extern f_notify_init notify_init; - -using f_notify_uninit = void (*)(void); -extern f_notify_uninit notify_uninit; - -using f_notify_is_initted = gboolean (*)(void); -extern f_notify_is_initted notify_is_initted; - -//using f_notify_get_app_name = const char* (*)(void); -//extern f_notify_get_app_name notify_get_app_name; - -//using f_notify_set_app_name = void (*)(const char *app_name); -//extern f_notify_set_app_name notify_set_app_name; - -using f_notify_get_server_caps = GList* (*)(void); -extern f_notify_get_server_caps notify_get_server_caps; - -using f_notify_get_server_info = gboolean (*)(char **ret_name, char **ret_vendor, char **ret_version, char **ret_spec_version); -extern f_notify_get_server_info notify_get_server_info; - -using f_notify_notification_new = NotifyNotification* (*)(const char *summary, const char *body, const char *icon); -extern f_notify_notification_new notify_notification_new; - -//using f_notify_notification_update = gboolean (*)(NotifyNotification *notification, const char *summary, const char *body, const char *icon); -//extern f_notify_notification_update notify_notification_update; - -using f_notify_notification_show = gboolean (*)(NotifyNotification *notification, GError **error); -extern f_notify_notification_show notify_notification_show; - -//using f_notify_notification_set_app_name = void (*)(NotifyNotification *notification, const char *app_name); -//extern f_notify_notification_set_app_name notify_notification_set_app_name; - -using f_notify_notification_set_timeout = void (*)(NotifyNotification *notification, gint timeout); -extern f_notify_notification_set_timeout notify_notification_set_timeout; - -//using f_notify_notification_set_category = void (*)(NotifyNotification *notification, const char *category); -//extern f_notify_notification_set_category notify_notification_set_category; - -//using f_notify_notification_set_urgency = void (*)(NotifyNotification *notification, NotifyUrgency urgency); -//extern f_notify_notification_set_urgency notify_notification_set_urgency; - -//using f_notify_notification_set_icon_from_pixbuf = void (*)(NotifyNotification *notification, GdkPixbuf *icon); -//extern f_notify_notification_set_icon_from_pixbuf notify_notification_set_icon_from_pixbuf; - -using f_notify_notification_set_image_from_pixbuf = void (*)(NotifyNotification *notification, GdkPixbuf *pixbuf); -extern f_notify_notification_set_image_from_pixbuf notify_notification_set_image_from_pixbuf; - -//using f_notify_notification_set_hint = void (*)(NotifyNotification *notification, const char *key, GVariant *value); -//extern f_notify_notification_set_hint notify_notification_set_hint; - -//using f_notify_notification_set_hint_int32 = void (*)(NotifyNotification *notification, const char *key, gint value); -//extern f_notify_notification_set_hint_int32 notify_notification_set_hint_int32; - -//using f_notify_notification_set_hint_uint32 = void (*)(NotifyNotification *notification, const char *key, guint value); -//extern f_notify_notification_set_hint_uint32 notify_notification_set_hint_uint32; - -//using f_notify_notification_set_hint_double = void (*)(NotifyNotification *notification, const char *key, gdouble value); -//extern f_notify_notification_set_hint_double notify_notification_set_hint_double; - -using f_notify_notification_set_hint_string = void (*)(NotifyNotification *notification, const char *key, const char *value); -extern f_notify_notification_set_hint_string notify_notification_set_hint_string; - -//using f_notify_notification_set_hint_byte = void (*)(NotifyNotification *notification, const char *key, guchar value); -//extern f_notify_notification_set_hint_byte notify_notification_set_hint_byte; - -//using f_notify_notification_set_hint_byte_array = void (*)(NotifyNotification *notification, const char *key, const guchar *value, gsize len); -//extern f_notify_notification_set_hint_byte_array notify_notification_set_hint_byte_array; - -//using f_notify_notification_clear_hints = void (*)(NotifyNotification *notification); -//extern f_notify_notification_clear_hints notify_notification_clear_hints; - -using f_notify_notification_add_action = void (*)(NotifyNotification *notification, const char *action, const char *label, NotifyActionCallback callback, gpointer user_data, GFreeFunc free_func); -extern f_notify_notification_add_action notify_notification_add_action; - -using f_notify_notification_clear_actions = void (*)(NotifyNotification *notification); -extern f_notify_notification_clear_actions notify_notification_clear_actions; - -using f_notify_notification_close = gboolean (*)(NotifyNotification *notification, GError **error); -extern f_notify_notification_close notify_notification_close; - -using f_notify_notification_get_closed_reason = gint (*)(const NotifyNotification *notification); -extern f_notify_notification_get_closed_reason notify_notification_get_closed_reason; - -} // namespace Libs -} // namespace Platform -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.cpp b/Telegram/SourceFiles/platform/linux/linux_libs.cpp index ae4b16376..5be78ce7f 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.cpp +++ b/Telegram/SourceFiles/platform/linux/linux_libs.cpp @@ -44,262 +44,17 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) { return false; } -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -bool setupGtkBase(QLibrary &lib_gtk) { - if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false; - if (!load(lib_gtk, "gtk_menu_new", gtk_menu_new)) return false; - if (!load(lib_gtk, "gtk_menu_get_type", gtk_menu_get_type)) return false; - - if (!load(lib_gtk, "gtk_menu_item_new_with_label", gtk_menu_item_new_with_label)) return false; - if (!load(lib_gtk, "gtk_menu_item_set_label", gtk_menu_item_set_label)) return false; - if (!load(lib_gtk, "gtk_menu_shell_append", gtk_menu_shell_append)) return false; - if (!load(lib_gtk, "gtk_menu_shell_get_type", gtk_menu_shell_get_type)) return false; - if (!load(lib_gtk, "gtk_widget_show", gtk_widget_show)) return false; - if (!load(lib_gtk, "gtk_widget_hide", gtk_widget_hide)) return false; - if (!load(lib_gtk, "gtk_widget_get_toplevel", gtk_widget_get_toplevel)) return false; - if (!load(lib_gtk, "gtk_widget_get_visible", gtk_widget_get_visible)) return false; - if (!load(lib_gtk, "gtk_widget_get_window", gtk_widget_get_window)) return false; - if (!load(lib_gtk, "gtk_widget_set_sensitive", gtk_widget_set_sensitive)) return false; - if (!load(lib_gtk, "gtk_widget_realize", gtk_widget_realize)) return false; - if (!load(lib_gtk, "gtk_widget_hide_on_delete", gtk_widget_hide_on_delete)) return false; - if (!load(lib_gtk, "gtk_widget_destroy", gtk_widget_destroy)) return false; - if (!load(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false; - if (!load(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false; - if (!load(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false; - if (!load(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false; - if (!load(lib_gtk, "gtk_image_get_type", gtk_image_get_type)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_current_folder", gtk_file_chooser_set_current_folder)) return false; - if (!load(lib_gtk, "gtk_file_chooser_get_current_folder", gtk_file_chooser_get_current_folder)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_current_name", gtk_file_chooser_set_current_name)) return false; - if (!load(lib_gtk, "gtk_file_chooser_select_filename", gtk_file_chooser_select_filename)) return false; - if (!load(lib_gtk, "gtk_file_chooser_get_filenames", gtk_file_chooser_get_filenames)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_filter", gtk_file_chooser_set_filter)) return false; - if (!load(lib_gtk, "gtk_file_chooser_get_filter", gtk_file_chooser_get_filter)) return false; - if (!load(lib_gtk, "gtk_window_get_type", gtk_window_get_type)) return false; - if (!load(lib_gtk, "gtk_window_set_title", gtk_window_set_title)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_local_only", gtk_file_chooser_set_local_only)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_action", gtk_file_chooser_set_action)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_select_multiple", gtk_file_chooser_set_select_multiple)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_do_overwrite_confirmation", gtk_file_chooser_set_do_overwrite_confirmation)) return false; - if (!load(lib_gtk, "gtk_file_chooser_remove_filter", gtk_file_chooser_remove_filter)) return false; - if (!load(lib_gtk, "gtk_file_filter_set_name", gtk_file_filter_set_name)) return false; - if (!load(lib_gtk, "gtk_file_filter_add_pattern", gtk_file_filter_add_pattern)) return false; - if (!load(lib_gtk, "gtk_file_chooser_add_filter", gtk_file_chooser_add_filter)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_preview_widget", gtk_file_chooser_set_preview_widget)) return false; - if (!load(lib_gtk, "gtk_file_chooser_get_preview_filename", gtk_file_chooser_get_preview_filename)) return false; - if (!load(lib_gtk, "gtk_file_chooser_set_preview_widget_active", gtk_file_chooser_set_preview_widget_active)) return false; - if (!load(lib_gtk, "gtk_file_filter_new", gtk_file_filter_new)) return false; - if (!load(lib_gtk, "gtk_image_new", gtk_image_new)) return false; - if (!load(lib_gtk, "gtk_image_set_from_pixbuf", gtk_image_set_from_pixbuf)) return false; - - if (!load(lib_gtk, "gdk_window_set_modal_hint", gdk_window_set_modal_hint)) return false; - if (!load(lib_gtk, "gdk_window_focus", gdk_window_focus)) return false; - if (!load(lib_gtk, "gtk_dialog_get_type", gtk_dialog_get_type)) return false; - if (!load(lib_gtk, "gtk_dialog_run", gtk_dialog_run)) return false; - - if (!load(lib_gtk, "g_type_check_instance_cast", g_type_check_instance_cast)) return false; - if (!load(lib_gtk, "g_type_check_instance_is_a", g_type_check_instance_is_a)) return false; - if (!load(lib_gtk, "g_signal_connect_data", g_signal_connect_data)) return false; - if (!load(lib_gtk, "g_signal_handler_disconnect", g_signal_handler_disconnect)) return false; - - if (!load(lib_gtk, "g_object_ref_sink", g_object_ref_sink)) return false; - if (!load(lib_gtk, "g_object_unref", g_object_unref)) return false; - if (!load(lib_gtk, "g_free", g_free)) return false; - if (!load(lib_gtk, "g_list_foreach", g_list_foreach)) return false; - if (!load(lib_gtk, "g_list_free", g_list_free)) return false; - if (!load(lib_gtk, "g_list_free_full", g_list_free_full)) return false; - - if (!load(lib_gtk, "g_error_free", g_error_free)) return false; - if (!load(lib_gtk, "g_slist_free", g_slist_free)) return false; - - DEBUG_LOG(("Library gtk functions loaded!")); - - if (load(lib_gtk, "gdk_set_allowed_backends", gdk_set_allowed_backends)) { - // We work only with X11 GDK backend. - // Otherwise we get segfault in Ubuntu 17.04 in gtk_init_check() call. - // See https://github.com/telegramdesktop/tdesktop/issues/3176 - // See https://github.com/telegramdesktop/tdesktop/issues/3162 - DEBUG_LOG(("Limit allowed GDK backends to x11")); - gdk_set_allowed_backends("x11"); - } - - DEBUG_LOG(("Library gtk functions loaded!")); - if (!gtk_init_check(0, 0)) { - gtk_init_check = nullptr; - DEBUG_LOG(("Failed to gtk_init_check(0, 0)!")); - return false; - } - - DEBUG_LOG(("Checked gtk with gtk_init_check!")); - return true; -} - -bool setupAppIndicator(QLibrary &lib_indicator) { - if (!load(lib_indicator, "app_indicator_new", app_indicator_new)) return false; - if (!load(lib_indicator, "app_indicator_set_status", app_indicator_set_status)) return false; - if (!load(lib_indicator, "app_indicator_set_menu", app_indicator_set_menu)) return false; - if (!load(lib_indicator, "app_indicator_set_icon_full", app_indicator_set_icon_full)) return false; - - DEBUG_LOG(("Library appindicator functions loaded!")); - return true; -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } // namespace -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -f_gtk_init_check gtk_init_check = nullptr; -f_gtk_menu_new gtk_menu_new = nullptr; -f_gtk_menu_get_type gtk_menu_get_type = nullptr; -f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label = nullptr; -f_gtk_menu_item_set_label gtk_menu_item_set_label = nullptr; -f_gtk_menu_shell_append gtk_menu_shell_append = nullptr; -f_gtk_menu_shell_get_type gtk_menu_shell_get_type = nullptr; -f_gtk_widget_show gtk_widget_show = nullptr; -f_gtk_widget_hide gtk_widget_hide = nullptr; -f_gtk_widget_get_toplevel gtk_widget_get_toplevel = nullptr; -f_gtk_widget_get_visible gtk_widget_get_visible = nullptr; -f_gtk_widget_get_window gtk_widget_get_window = nullptr; -f_gtk_widget_set_sensitive gtk_widget_set_sensitive = 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_clipboard_get gtk_clipboard_get = nullptr; -f_gtk_clipboard_store gtk_clipboard_store = nullptr; -f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new = nullptr; -f_gtk_file_chooser_get_type gtk_file_chooser_get_type = nullptr; -f_gtk_image_get_type gtk_image_get_type = nullptr; -f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder = nullptr; -f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder = nullptr; -f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name = nullptr; -f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename = nullptr; -f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames = nullptr; -f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter = nullptr; -f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter = nullptr; -f_gtk_window_get_type gtk_window_get_type = nullptr; -f_gtk_window_set_title gtk_window_set_title = nullptr; -f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only = nullptr; -f_gtk_file_chooser_set_action gtk_file_chooser_set_action = nullptr; -f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple = nullptr; -f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation = nullptr; -f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter = nullptr; -f_gtk_file_filter_set_name gtk_file_filter_set_name = nullptr; -f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern = nullptr; -f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter = nullptr; -f_gtk_file_chooser_set_preview_widget gtk_file_chooser_set_preview_widget = nullptr; -f_gtk_file_chooser_get_preview_filename gtk_file_chooser_get_preview_filename = nullptr; -f_gtk_file_chooser_set_preview_widget_active gtk_file_chooser_set_preview_widget_active = nullptr; -f_gtk_file_filter_new gtk_file_filter_new = nullptr; -f_gtk_image_new gtk_image_new = nullptr; -f_gtk_image_set_from_pixbuf gtk_image_set_from_pixbuf = nullptr; -f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response = nullptr; -f_gtk_button_set_label gtk_button_set_label = nullptr; -f_gtk_button_get_type gtk_button_get_type = nullptr; -f_gdk_set_allowed_backends gdk_set_allowed_backends = nullptr; -f_gdk_window_set_modal_hint gdk_window_set_modal_hint = nullptr; -f_gdk_window_focus gdk_window_focus = nullptr; -f_gtk_dialog_get_type gtk_dialog_get_type = nullptr; -f_gtk_dialog_run gtk_dialog_run = nullptr; -f_g_type_check_instance_cast g_type_check_instance_cast = nullptr; -f_g_type_check_instance_is_a g_type_check_instance_is_a = nullptr; -f_g_signal_connect_data g_signal_connect_data = nullptr; -f_g_signal_handler_disconnect g_signal_handler_disconnect = nullptr; -f_app_indicator_new app_indicator_new = nullptr; -f_app_indicator_set_status app_indicator_set_status = nullptr; -f_app_indicator_set_menu app_indicator_set_menu = nullptr; -f_app_indicator_set_icon_full app_indicator_set_icon_full = nullptr; -f_gdk_init_check gdk_init_check = nullptr; -f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr; -f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file = nullptr; -f_gdk_pixbuf_new_from_file_at_size gdk_pixbuf_new_from_file_at_size = nullptr; -f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf = nullptr; -f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf = nullptr; -f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file = nullptr; -f_gtk_status_icon_set_from_file gtk_status_icon_set_from_file = nullptr; -f_gtk_status_icon_set_title gtk_status_icon_set_title = nullptr; -f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text = nullptr; -f_gtk_status_icon_set_visible gtk_status_icon_set_visible = nullptr; -f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded = nullptr; -f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry = nullptr; -f_gtk_status_icon_position_menu gtk_status_icon_position_menu = nullptr; -f_gtk_menu_popup gtk_menu_popup = nullptr; -f_gtk_get_current_event_time gtk_get_current_event_time = nullptr; -f_g_object_ref_sink g_object_ref_sink = nullptr; -f_g_object_unref g_object_unref = nullptr; -f_g_idle_add g_idle_add = nullptr; -f_g_free g_free = nullptr; -f_g_list_foreach g_list_foreach = nullptr; -f_g_list_free g_list_free = nullptr; -f_g_list_free_full g_list_free_full = nullptr; -f_g_error_free g_error_free = nullptr; -f_g_slist_free g_slist_free = nullptr; #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr; f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_visible = nullptr; f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr; #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION void start() { DEBUG_LOG(("Loading libraries")); -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - - bool gtkLoaded = false; - bool indicatorLoaded = false; - QLibrary lib_gtk, lib_indicator; - if (loadLibrary(lib_indicator, "appindicator3", 1)) { - if (loadLibrary(lib_gtk, "gtk-3", 0)) { - gtkLoaded = setupGtkBase(lib_gtk); - indicatorLoaded = setupAppIndicator(lib_indicator); - } - } - if (!gtkLoaded || !indicatorLoaded) { - if (loadLibrary(lib_indicator, "appindicator", 1)) { - if (loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { - gtkLoaded = indicatorLoaded = false; - gtkLoaded = setupGtkBase(lib_gtk); - indicatorLoaded = setupAppIndicator(lib_indicator); - } - } - } - - // If no appindicator, try at least load gtk. - if (!gtkLoaded && !indicatorLoaded) { - if (loadLibrary(lib_gtk, "gtk-3", 0)) { - gtkLoaded = setupGtkBase(lib_gtk); - } - if (!gtkLoaded && loadLibrary(lib_gtk, "gtk-x11-2.0", 0)) { - gtkLoaded = setupGtkBase(lib_gtk); - } - } - - if (gtkLoaded) { - load(lib_gtk, "gdk_init_check", gdk_init_check); - load(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data); - load(lib_gtk, "gdk_pixbuf_new_from_file", gdk_pixbuf_new_from_file); - load(lib_gtk, "gdk_pixbuf_new_from_file_at_size", gdk_pixbuf_new_from_file_at_size); - load(lib_gtk, "gtk_status_icon_new_from_pixbuf", gtk_status_icon_new_from_pixbuf); - load(lib_gtk, "gtk_status_icon_set_from_pixbuf", gtk_status_icon_set_from_pixbuf); - load(lib_gtk, "gtk_status_icon_new_from_file", gtk_status_icon_new_from_file); - load(lib_gtk, "gtk_status_icon_set_from_file", gtk_status_icon_set_from_file); - load(lib_gtk, "gtk_status_icon_set_title", gtk_status_icon_set_title); - load(lib_gtk, "gtk_status_icon_set_tooltip_text", gtk_status_icon_set_tooltip_text); - load(lib_gtk, "gtk_status_icon_set_visible", gtk_status_icon_set_visible); - load(lib_gtk, "gtk_status_icon_is_embedded", gtk_status_icon_is_embedded); - load(lib_gtk, "gtk_status_icon_get_geometry", gtk_status_icon_get_geometry); - load(lib_gtk, "gtk_status_icon_position_menu", gtk_status_icon_position_menu); - load(lib_gtk, "gtk_menu_popup", gtk_menu_popup); - load(lib_gtk, "gtk_get_current_event_time", gtk_get_current_event_time); - load(lib_gtk, "g_idle_add", g_idle_add); - - internal::GdkHelperLoad(lib_gtk); - - load(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response); - load(lib_gtk, "gtk_button_set_label", gtk_button_set_label); - load(lib_gtk, "gtk_button_get_type", gtk_button_get_type); - } else { - LOG(("Could not load gtk-x11-2.0!")); - } #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION if (DesktopEnvironment::TryUnityCounter()) { @@ -311,11 +66,6 @@ void start() { load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible); } #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION - - if (gtkLoaded) { - startLibNotify(); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } } // namespace Libs diff --git a/Telegram/SourceFiles/platform/linux/linux_libs.h b/Telegram/SourceFiles/platform/linux/linux_libs.h index e9e349be9..5460094b1 100644 --- a/Telegram/SourceFiles/platform/linux/linux_libs.h +++ b/Telegram/SourceFiles/platform/linux/linux_libs.h @@ -20,19 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -extern "C" { -#undef signals -#include <libappindicator/app-indicator.h> -#include <gtk/gtk.h> -#include <gdk/gdk.h> -#define signals public -} // extern "C" - #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION #include <unity/unity/unity.h> #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION namespace Platform { namespace Libs { @@ -54,326 +44,6 @@ bool load(QLibrary &lib, const char *name, Function &func) { return false; } -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -typedef gboolean (*f_gtk_init_check)(int *argc, char ***argv); -extern f_gtk_init_check gtk_init_check; - -typedef GtkWidget* (*f_gtk_menu_new)(void); -extern f_gtk_menu_new gtk_menu_new; - -typedef GType (*f_gtk_menu_get_type)(void) G_GNUC_CONST; -extern f_gtk_menu_get_type gtk_menu_get_type; - -typedef GtkWidget* (*f_gtk_menu_item_new_with_label)(const gchar *label); -extern f_gtk_menu_item_new_with_label gtk_menu_item_new_with_label; - -typedef void (*f_gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label); -extern f_gtk_menu_item_set_label gtk_menu_item_set_label; - -typedef void (*f_gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child); -extern f_gtk_menu_shell_append gtk_menu_shell_append; - -typedef GType (*f_gtk_menu_shell_get_type)(void) G_GNUC_CONST; -extern f_gtk_menu_shell_get_type gtk_menu_shell_get_type; - -typedef void (*f_gtk_widget_show)(GtkWidget *widget); -extern f_gtk_widget_show gtk_widget_show; - -typedef void (*f_gtk_widget_hide)(GtkWidget *widget); -extern f_gtk_widget_hide gtk_widget_hide; - -typedef GtkWidget* (*f_gtk_widget_get_toplevel)(GtkWidget *widget); -extern f_gtk_widget_get_toplevel gtk_widget_get_toplevel; - -typedef gboolean (*f_gtk_widget_get_visible)(GtkWidget *widget); -extern f_gtk_widget_get_visible gtk_widget_get_visible; - -typedef GdkWindow* (*f_gtk_widget_get_window)(GtkWidget *widget); -extern f_gtk_widget_get_window gtk_widget_get_window; - -typedef void (*f_gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive); -extern f_gtk_widget_set_sensitive gtk_widget_set_sensitive; - -typedef void (*f_gtk_widget_realize)(GtkWidget *widget); -extern f_gtk_widget_realize gtk_widget_realize; - -typedef gboolean (*f_gtk_widget_hide_on_delete)(GtkWidget *widget); -extern f_gtk_widget_hide_on_delete gtk_widget_hide_on_delete; - -typedef void (*f_gtk_widget_destroy)(GtkWidget *widget); -extern f_gtk_widget_destroy gtk_widget_destroy; - -typedef GtkClipboard* (*f_gtk_clipboard_get)(GdkAtom selection); -extern f_gtk_clipboard_get gtk_clipboard_get; - -typedef void (*f_gtk_clipboard_store)(GtkClipboard *clipboard); -extern f_gtk_clipboard_store gtk_clipboard_store; - -typedef GtkWidget* (*f_gtk_file_chooser_dialog_new)(const gchar *title, GtkWindow *parent, GtkFileChooserAction action, const gchar *first_button_text, ...) G_GNUC_NULL_TERMINATED; -extern f_gtk_file_chooser_dialog_new gtk_file_chooser_dialog_new; - -typedef gboolean (*f_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser, const gchar *filename); -extern f_gtk_file_chooser_set_current_folder gtk_file_chooser_set_current_folder; - -typedef gchar* (*f_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser); -extern f_gtk_file_chooser_get_current_folder gtk_file_chooser_get_current_folder; - -typedef void (*f_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser, const gchar *name); -extern f_gtk_file_chooser_set_current_name gtk_file_chooser_set_current_name; - -typedef gboolean (*f_gtk_file_chooser_select_filename)(GtkFileChooser *chooser, const gchar *filename); -extern f_gtk_file_chooser_select_filename gtk_file_chooser_select_filename; - -typedef GSList* (*f_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser); -extern f_gtk_file_chooser_get_filenames gtk_file_chooser_get_filenames; - -typedef void (*f_gtk_file_chooser_set_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -extern f_gtk_file_chooser_set_filter gtk_file_chooser_set_filter; - -typedef GtkFileFilter* (*f_gtk_file_chooser_get_filter)(GtkFileChooser *chooser); -extern f_gtk_file_chooser_get_filter gtk_file_chooser_get_filter; - -typedef void (*f_gtk_window_set_title)(GtkWindow *window, const gchar *title); -extern f_gtk_window_set_title gtk_window_set_title; - -typedef void (*f_gtk_file_chooser_set_local_only)(GtkFileChooser *chooser, gboolean local_only); -extern f_gtk_file_chooser_set_local_only gtk_file_chooser_set_local_only; - -typedef void (*f_gtk_file_chooser_set_action)(GtkFileChooser *chooser, GtkFileChooserAction action); -extern f_gtk_file_chooser_set_action gtk_file_chooser_set_action; - -typedef void (*f_gtk_file_chooser_set_select_multiple)(GtkFileChooser *chooser, gboolean select_multiple); -extern f_gtk_file_chooser_set_select_multiple gtk_file_chooser_set_select_multiple; - -typedef void (*f_gtk_file_chooser_set_do_overwrite_confirmation)(GtkFileChooser *chooser, gboolean do_overwrite_confirmation); -extern f_gtk_file_chooser_set_do_overwrite_confirmation gtk_file_chooser_set_do_overwrite_confirmation; - -typedef GtkWidget* (*f_gtk_dialog_get_widget_for_response)(GtkDialog *dialog, gint response_id); -extern f_gtk_dialog_get_widget_for_response gtk_dialog_get_widget_for_response; - -typedef void (*f_gtk_button_set_label)(GtkButton *button, const gchar *label); -extern f_gtk_button_set_label gtk_button_set_label; - -typedef void (*f_gtk_file_chooser_remove_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -extern f_gtk_file_chooser_remove_filter gtk_file_chooser_remove_filter; - -typedef void (*f_gtk_file_filter_set_name)(GtkFileFilter *filter, const gchar *name); -extern f_gtk_file_filter_set_name gtk_file_filter_set_name; - -typedef void (*f_gtk_file_filter_add_pattern)(GtkFileFilter *filter, const gchar *pattern); -extern f_gtk_file_filter_add_pattern gtk_file_filter_add_pattern; - -typedef void (*f_gtk_file_chooser_add_filter)(GtkFileChooser *chooser, GtkFileFilter *filter); -extern f_gtk_file_chooser_add_filter gtk_file_chooser_add_filter; - -typedef void (*f_gtk_file_chooser_set_preview_widget)(GtkFileChooser *chooser, GtkWidget *preview_widget); -extern f_gtk_file_chooser_set_preview_widget gtk_file_chooser_set_preview_widget; - -typedef gchar* (*f_gtk_file_chooser_get_preview_filename)(GtkFileChooser *chooser); -extern f_gtk_file_chooser_get_preview_filename gtk_file_chooser_get_preview_filename; - -typedef void (*f_gtk_file_chooser_set_preview_widget_active)(GtkFileChooser *chooser, gboolean active); -extern f_gtk_file_chooser_set_preview_widget_active gtk_file_chooser_set_preview_widget_active; - -typedef GtkFileFilter* (*f_gtk_file_filter_new)(void); -extern f_gtk_file_filter_new gtk_file_filter_new; - -typedef GtkWidget* (*f_gtk_image_new)(void); -extern f_gtk_image_new gtk_image_new; - -typedef void (*f_gtk_image_set_from_pixbuf)(GtkImage *image, GdkPixbuf *pixbuf); -extern f_gtk_image_set_from_pixbuf gtk_image_set_from_pixbuf; - -typedef void (*f_gdk_set_allowed_backends)(const gchar *backends); -extern f_gdk_set_allowed_backends gdk_set_allowed_backends; - -typedef void (*f_gdk_window_set_modal_hint)(GdkWindow *window, gboolean modal); -extern f_gdk_window_set_modal_hint gdk_window_set_modal_hint; - -typedef void (*f_gdk_window_focus)(GdkWindow *window, guint32 timestamp); -extern f_gdk_window_focus gdk_window_focus; - -typedef GTypeInstance* (*f_g_type_check_instance_cast)(GTypeInstance *instance, GType iface_type); -extern f_g_type_check_instance_cast g_type_check_instance_cast; - -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)); -} - -template <typename Object> -inline GtkMenu *gtk_menu_cast(Object *obj) { - return g_type_cic_helper<GtkMenu, Object>(obj, gtk_menu_get_type()); -} - -template <typename Object> -inline GtkMenuShell *gtk_menu_shell_cast(Object *obj) { - return g_type_cic_helper<GtkMenuShell, Object>(obj, gtk_menu_get_type()); -} - -typedef GType (*f_gtk_dialog_get_type)(void) G_GNUC_CONST; -extern f_gtk_dialog_get_type gtk_dialog_get_type; - -template <typename Object> -inline GtkDialog *gtk_dialog_cast(Object *obj) { - return g_type_cic_helper<GtkDialog, Object>(obj, gtk_dialog_get_type()); -} - -template <typename Object> -inline GObject *g_object_cast(Object *obj) { - return g_type_cic_helper<GObject, Object>(obj, G_TYPE_OBJECT); -} - -typedef GType (*f_gtk_file_chooser_get_type)(void) G_GNUC_CONST; -extern f_gtk_file_chooser_get_type gtk_file_chooser_get_type; - -template <typename Object> -inline GtkFileChooser *gtk_file_chooser_cast(Object *obj) { - return g_type_cic_helper<GtkFileChooser, Object>(obj, gtk_file_chooser_get_type()); -} - -typedef GType (*f_gtk_image_get_type)(void) G_GNUC_CONST; -extern f_gtk_image_get_type gtk_image_get_type; - -template <typename Object> -inline GtkImage *gtk_image_cast(Object *obj) { - return g_type_cic_helper<GtkImage, Object>(obj, gtk_image_get_type()); -} - -typedef GType (*f_gtk_button_get_type)(void) G_GNUC_CONST; -extern f_gtk_button_get_type gtk_button_get_type; - -template <typename Object> -inline GtkButton *gtk_button_cast(Object *obj) { - return g_type_cic_helper<GtkButton, Object>(obj, gtk_button_get_type()); -} - -typedef GType (*f_gtk_window_get_type)(void) G_GNUC_CONST; -extern f_gtk_window_get_type gtk_window_get_type; - -template <typename Object> -inline GtkWindow *gtk_window_cast(Object *obj) { - return g_type_cic_helper<GtkWindow, Object>(obj, gtk_window_get_type()); -} - -typedef gboolean (*f_g_type_check_instance_is_a)(GTypeInstance *instance, GType iface_type); -extern f_g_type_check_instance_is_a g_type_check_instance_is_a; - -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); -} - -typedef gint (*f_gtk_dialog_run)(GtkDialog *dialog); -extern f_gtk_dialog_run gtk_dialog_run; - -typedef gulong (*f_g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); -extern f_g_signal_connect_data g_signal_connect_data; - -inline gulong g_signal_connect_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data = nullptr) { - return g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, (GConnectFlags)0); -} - -inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data = nullptr) { - return g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, G_CONNECT_SWAPPED); -} - -typedef void (*f_g_signal_handler_disconnect)(gpointer instance, gulong handler_id); -extern f_g_signal_handler_disconnect g_signal_handler_disconnect; - -typedef AppIndicator* (*f_app_indicator_new)(const gchar *id, const gchar *icon_name, AppIndicatorCategory category); -extern f_app_indicator_new app_indicator_new; - -typedef void (*f_app_indicator_set_status)(AppIndicator *self, AppIndicatorStatus status); -extern f_app_indicator_set_status app_indicator_set_status; - -typedef void (*f_app_indicator_set_menu)(AppIndicator *self, GtkMenu *menu); -extern f_app_indicator_set_menu app_indicator_set_menu; - -typedef void (*f_app_indicator_set_icon_full)(AppIndicator *self, const gchar *icon_name, const gchar *icon_desc); -extern f_app_indicator_set_icon_full app_indicator_set_icon_full; - -typedef gboolean (*f_gdk_init_check)(gint *argc, gchar ***argv); -extern f_gdk_init_check gdk_init_check; - -typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_data)(const guchar *data, GdkColorspace colorspace, gboolean has_alpha, int bits_per_sample, int width, int height, int rowstride, GdkPixbufDestroyNotify destroy_fn, gpointer destroy_fn_data); -extern f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data; - -typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_file)(const gchar *filename, GError **error); -extern f_gdk_pixbuf_new_from_file gdk_pixbuf_new_from_file; - -typedef GdkPixbuf* (*f_gdk_pixbuf_new_from_file_at_size)(const gchar *filename, int width, int height, GError **error); -extern f_gdk_pixbuf_new_from_file_at_size gdk_pixbuf_new_from_file_at_size; - -typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_pixbuf)(GdkPixbuf *pixbuf); -extern f_gtk_status_icon_new_from_pixbuf gtk_status_icon_new_from_pixbuf; - -typedef void (*f_gtk_status_icon_set_from_pixbuf)(GtkStatusIcon *status_icon, GdkPixbuf *pixbuf); -extern f_gtk_status_icon_set_from_pixbuf gtk_status_icon_set_from_pixbuf; - -typedef GtkStatusIcon* (*f_gtk_status_icon_new_from_file)(const gchar *filename); -extern f_gtk_status_icon_new_from_file gtk_status_icon_new_from_file; - -typedef void (*f_gtk_status_icon_set_from_file)(GtkStatusIcon *status_icon, const gchar *filename); -extern f_gtk_status_icon_set_from_file gtk_status_icon_set_from_file; - -typedef void (*f_gtk_status_icon_set_title)(GtkStatusIcon *status_icon, const gchar *title); -extern f_gtk_status_icon_set_title gtk_status_icon_set_title; - -typedef void (*f_gtk_status_icon_set_tooltip_text)(GtkStatusIcon *status_icon, const gchar *title); -extern f_gtk_status_icon_set_tooltip_text gtk_status_icon_set_tooltip_text; - -typedef void (*f_gtk_status_icon_set_visible)(GtkStatusIcon *status_icon, gboolean visible); -extern f_gtk_status_icon_set_visible gtk_status_icon_set_visible; - -typedef gboolean (*f_gtk_status_icon_is_embedded)(GtkStatusIcon *status_icon); -extern f_gtk_status_icon_is_embedded gtk_status_icon_is_embedded; - -typedef gboolean (*f_gtk_status_icon_get_geometry)(GtkStatusIcon *status_icon, GdkScreen **screen, GdkRectangle *area, GtkOrientation *orientation); -extern f_gtk_status_icon_get_geometry gtk_status_icon_get_geometry; - -typedef void (*f_gtk_status_icon_position_menu)(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data); -extern f_gtk_status_icon_position_menu gtk_status_icon_position_menu; - -typedef void (*f_gtk_menu_popup)(GtkMenu *menu, GtkWidget *parent_menu_shell, GtkWidget *parent_menu_item, GtkMenuPositionFunc func, gpointer data, guint button, guint32 activate_time); -extern f_gtk_menu_popup gtk_menu_popup; - -typedef guint32 (*f_gtk_get_current_event_time)(void); -extern f_gtk_get_current_event_time gtk_get_current_event_time; - -typedef gpointer (*f_g_object_ref_sink)(gpointer object); -extern f_g_object_ref_sink g_object_ref_sink; - -typedef void (*f_g_object_unref)(gpointer object); -extern f_g_object_unref g_object_unref; - -typedef guint (*f_g_idle_add)(GSourceFunc function, gpointer data); -extern f_g_idle_add g_idle_add; - -typedef void (*f_g_free)(gpointer mem); -extern f_g_free g_free; - -typedef void (*f_g_list_foreach)(GList *list, GFunc func, gpointer user_data); -extern f_g_list_foreach g_list_foreach; - -typedef void (*f_g_list_free)(GList *list); -extern f_g_list_free g_list_free; - -typedef void (*f_g_list_free_full)(GList *list, GDestroyNotify free_func); -extern f_g_list_free_full g_list_free_full; - -typedef void (*f_g_error_free)(GError *error); -extern f_g_error_free g_error_free; - -typedef void (*f_g_slist_free)(GSList *list); -extern f_g_slist_free g_slist_free; - #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value); extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count; @@ -384,7 +54,6 @@ extern f_unity_launcher_entry_set_count_visible unity_launcher_entry_set_count_v typedef UnityLauncherEntry* (*f_unity_launcher_entry_get_for_desktop_id)(const gchar* desktop_id); extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id; #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } // namespace Libs } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp index d12350fc2..a82c99661 100644 --- a/Telegram/SourceFiles/platform/linux/main_window_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/main_window_linux.cpp @@ -36,51 +36,18 @@ namespace { bool noQtTrayIcon = false, tryAppIndicator = false; bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = false; -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -AppIndicator *_trayIndicator = 0; -GtkStatusIcon *_trayIcon = 0; -GtkWidget *_trayMenu = 0; -GdkPixbuf *_trayPixbuf = 0; -QByteArray _trayPixbufData; -QList<QPair<GtkWidget*, QObject*> > _trayItems; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION qint32 _trayIconSize = 22; bool _trayIconMuted = true; qint32 _trayIconCount = 0; QImage _trayIconImageBack, _trayIconImage; -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -void _trayIconPopup(GtkStatusIcon *status_icon, guint button, guint32 activate_time, gpointer popup_menu) { - Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, button, activate_time); -} - -void _trayIconActivate(GtkStatusIcon *status_icon, gpointer popup_menu) { - if (App::wnd()->isActiveWindow() && App::wnd()->isVisible()) { - Libs::gtk_menu_popup(Libs::gtk_menu_cast(popup_menu), NULL, NULL, Libs::gtk_status_icon_position_menu, status_icon, 0, Libs::gtk_get_current_event_time()); - } else { - App::wnd()->showFromTray(); - } -} - -gboolean _trayIconResized(GtkStatusIcon *status_icon, gint size, gpointer popup_menu) { - _trayIconSize = size; - if (Global::started()) Notify::unreadCounterUpdated(); - return FALSE; -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION #define QT_RED 0 #define QT_GREEN 1 #define QT_BLUE 2 #define QT_ALPHA 3 -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -#define GTK_RED 2 -#define GTK_GREEN 1 -#define GTK_BLUE 0 -#define GTK_ALPHA 3 -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION QImage _trayIconImageGen() { qint32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter; @@ -139,55 +106,10 @@ QString _trayIconImageFile() { return QString(); } -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - -void loadPixbuf(QImage image) { - int w = image.width(), h = image.height(), perline = image.bytesPerLine(), s = image.byteCount(); - _trayPixbufData.resize(w * h * 4); - uchar *result = (uchar*)_trayPixbufData.data(), *bytes = image.bits(); - for (qint32 y = 0; y < h; ++y) { - for (qint32 x = 0; x < w; ++x) { - qint32 offset = (y * w + x) * 4, srcoff = y * perline + x * 4; - result[offset + GTK_RED ] = bytes[srcoff + QT_RED ]; - result[offset + GTK_GREEN] = bytes[srcoff + QT_GREEN]; - result[offset + GTK_BLUE ] = bytes[srcoff + QT_BLUE ]; - result[offset + GTK_ALPHA] = bytes[srcoff + QT_ALPHA]; - } - } - - if (_trayPixbuf) Libs::g_object_unref(_trayPixbuf); - _trayPixbuf = Libs::gdk_pixbuf_new_from_data(result, GDK_COLORSPACE_RGB, true, 8, w, h, w * 4, 0, 0); -} - -void _trayMenuCallback(GtkMenu *menu, gpointer data) { - for (qint32 i = 0, l = _trayItems.size(); i < l; ++i) { - if ((void*)_trayItems.at(i).first == (void*)menu) { - QMetaObject::invokeMethod(_trayItems.at(i).second, "triggered"); - } - } -} - -static gboolean _trayIconCheck(gpointer/* pIn*/) { - if (useStatusIcon && !trayIconChecked) { - if (Libs::gtk_status_icon_is_embedded(_trayIcon)) { - trayIconChecked = true; - cSetSupportTray(true); - if (Global::started()) { - Global::RefWorkMode().setForced(Global::WorkMode().value(), true); - } - if (App::wnd()) { - Notify::unreadCounterUpdated(); - App::wnd()->updateTrayMenu(); - } - } - } - return FALSE; -} #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION UnityLauncherEntry *_psUnityLauncherEntry = nullptr; #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } // namespace @@ -200,17 +122,10 @@ MainWindow::MainWindow() { } bool MainWindow::hasTrayIcon() const { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (Global::WorkMode().value() != dbiwmWindowOnly)); -#else return trayIcon; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } void MainWindow::psStatusIconCheck() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - _trayIconCheck(0); -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION if (cSupportTray() || !--_psCheckStatusIconLeft) { _psCheckStatusIconTimer.stop(); return; @@ -221,31 +136,6 @@ void MainWindow::psShowTrayMenu() { } void MainWindow::psTrayMenuUpdated() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (noQtTrayIcon && (useAppIndicator || useStatusIcon)) { - const QList<QAction*> &actions = trayIconMenu->actions(); - if (_trayItems.isEmpty()) { - DEBUG_LOG(("Creating tray menu!")); - for (qint32 i = 0, l = actions.size(); i != l; ++i) { - GtkWidget *item = Libs::gtk_menu_item_new_with_label(actions.at(i)->text().toUtf8()); - Libs::gtk_menu_shell_append(Libs::gtk_menu_shell_cast(_trayMenu), item); - Libs::g_signal_connect_helper(item, "activate", G_CALLBACK(_trayMenuCallback), this); - Libs::gtk_widget_show(item); - Libs::gtk_widget_set_sensitive(item, actions.at(i)->isEnabled()); - - _trayItems.push_back(qMakePair(item, actions.at(i))); - } - } else { - DEBUG_LOG(("Updating tray menu!")); - for (qint32 i = 0, l = actions.size(); i != l; ++i) { - if (i < _trayItems.size()) { - Libs::gtk_menu_item_set_label(reinterpret_cast<GtkMenuItem*>(_trayItems.at(i).first), actions.at(i)->text().toUtf8()); - Libs::gtk_widget_set_sensitive(_trayItems.at(i).first, actions.at(i)->isEnabled()); - } - } - } - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } void MainWindow::psSetupTrayIcon() { @@ -289,13 +179,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { if (mode == dbiwmWindowOnly) { if (noQtTrayIcon) { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (useAppIndicator) { - Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_PASSIVE); - } else if (useStatusIcon) { - Libs::gtk_status_icon_set_visible(_trayIcon, false); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } else { if (trayIcon) { trayIcon->setContextMenu(0); @@ -305,13 +188,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } } else { if (noQtTrayIcon) { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (useAppIndicator) { - Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); - } else if (useStatusIcon) { - Libs::gtk_status_icon_set_visible(_trayIcon, true); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } else { psSetupTrayIcon(); } @@ -319,18 +195,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) { } void MainWindow::psUpdateIndicator() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - _psUpdateIndicatorTimer.stop(); - _psLastIndicatorUpdate = getms(); - QFileInfo iconFile(_trayIconImageFile()); - if (iconFile.exists()) { - QByteArray path = QFile::encodeName(iconFile.absoluteFilePath()), name = QFile::encodeName(iconFile.fileName()); - name = name.mid(0, name.size() - 4); - Libs::app_indicator_set_icon_full(_trayIndicator, path.constData(), name); - } else { - useAppIndicator = false; - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } void MainWindow::unreadCounterChangedHook() { @@ -343,7 +207,7 @@ void MainWindow::updateIconCounters() { auto counter = App::histories().unreadBadge(); -#if !defined(TDESKTOP_DISABLE_GTK_INTEGRATION) && !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION) +#if !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION) if (_psUnityLauncherEntry) { if (counter > 0) { Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter); @@ -352,27 +216,9 @@ void MainWindow::updateIconCounters() { Libs::unity_launcher_entry_set_count_visible(_psUnityLauncherEntry, FALSE); } } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION && !TDESKTOP_DISABLE_UNITY_INTEGRATION +#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION if (noQtTrayIcon) { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (useAppIndicator) { - if (getms() > _psLastIndicatorUpdate + 1000) { - psUpdateIndicator(); - } else if (!_psUpdateIndicatorTimer.isActive()) { - _psUpdateIndicatorTimer.start(100); - } - } else if (useStatusIcon && trayIconChecked) { - QFileInfo iconFile(_trayIconImageFile()); - if (iconFile.exists()) { - QByteArray path = QFile::encodeName(iconFile.absoluteFilePath()); - Libs::gtk_status_icon_set_from_file(_trayIcon, path.constData()); - } else { - loadPixbuf(_trayIconImageGen()); - Libs::gtk_status_icon_set_from_pixbuf(_trayIcon, _trayPixbuf); - } - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } else if (trayIcon) { QIcon icon; QFileInfo iconFile(_trayIconImageFile()); @@ -394,61 +240,11 @@ void MainWindow::updateIconCounters() { void MainWindow::LibsLoaded() { noQtTrayIcon = !DesktopEnvironment::TryQtTrayIcon(); -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - tryAppIndicator = DesktopEnvironment::PreferAppIndicatorTrayIcon(); -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION LOG(("Tray Icon: Try Qt = %1, Prefer appindicator = %2").arg(Logs::b(!noQtTrayIcon)).arg(Logs::b(tryAppIndicator))); if (noQtTrayIcon) cSetSupportTray(false); -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - useGtkBase = (Libs::gtk_init_check != nullptr) - && (Libs::gtk_menu_new != nullptr) - && (Libs::gtk_menu_get_type != nullptr) - && (Libs::gtk_menu_item_new_with_label != nullptr) - && (Libs::gtk_menu_item_set_label != nullptr) - && (Libs::gtk_menu_shell_append != nullptr) - && (Libs::gtk_menu_shell_get_type != nullptr) - && (Libs::gtk_widget_show != nullptr) - && (Libs::gtk_widget_get_toplevel != nullptr) - && (Libs::gtk_widget_get_visible != nullptr) - && (Libs::gtk_widget_set_sensitive != nullptr) - && (Libs::g_type_check_instance_cast != nullptr) - && (Libs::g_signal_connect_data != nullptr) - && (Libs::g_object_ref_sink != nullptr) - && (Libs::g_object_unref != nullptr); - - useAppIndicator = useGtkBase - && (Libs::app_indicator_new != nullptr) - && (Libs::app_indicator_set_status != nullptr) - && (Libs::app_indicator_set_menu != nullptr) - && (Libs::app_indicator_set_icon_full != nullptr); - - if (tryAppIndicator && useGtkBase && useAppIndicator) { - noQtTrayIcon = true; - cSetSupportTray(false); - } - - useStatusIcon = (Libs::gdk_init_check != nullptr) - && (Libs::gdk_pixbuf_new_from_data != nullptr) - && (Libs::gtk_status_icon_new_from_pixbuf != nullptr) - && (Libs::gtk_status_icon_set_from_pixbuf != nullptr) - && (Libs::gtk_status_icon_new_from_file != nullptr) - && (Libs::gtk_status_icon_set_from_file != nullptr) - && (Libs::gtk_status_icon_set_title != nullptr) - && (Libs::gtk_status_icon_set_tooltip_text != nullptr) - && (Libs::gtk_status_icon_set_visible != nullptr) - && (Libs::gtk_status_icon_is_embedded != nullptr) - && (Libs::gtk_status_icon_get_geometry != nullptr) - && (Libs::gtk_status_icon_position_menu != nullptr) - && (Libs::gtk_menu_popup != nullptr) - && (Libs::gtk_get_current_event_time != nullptr) - && (Libs::g_idle_add != nullptr); - if (useStatusIcon) { - DEBUG_LOG(("Status icon api loaded!")); - } - #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr) && (Libs::unity_launcher_entry_set_count != nullptr) @@ -457,7 +253,6 @@ void MainWindow::LibsLoaded() { DEBUG_LOG(("Unity count api loaded!")); } #endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } void MainWindow::psCreateTrayIcon() { @@ -466,92 +261,12 @@ void MainWindow::psCreateTrayIcon() { cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable()); return; } - -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (useAppIndicator) { - DEBUG_LOG(("Trying to create AppIndicator")); - _trayMenu = Libs::gtk_menu_new(); - if (_trayMenu) { - DEBUG_LOG(("Created gtk menu for appindicator!")); - QFileInfo iconFile(_trayIconImageFile()); - if (iconFile.exists()) { - QByteArray path = QFile::encodeName(iconFile.absoluteFilePath()); - _trayIndicator = Libs::app_indicator_new(AppName.c_str(), path.constData(), APP_INDICATOR_CATEGORY_APPLICATION_STATUS); - if (_trayIndicator) { - LOG(("Tray Icon: Using appindicator tray icon.")); - } else { - DEBUG_LOG(("Failed to app_indicator_new()!")); - } - } else { - useAppIndicator = false; - DEBUG_LOG(("Failed to create image file!")); - } - } else { - DEBUG_LOG(("Failed to gtk_menu_new()!")); - } - if (_trayMenu && _trayIndicator) { - Libs::app_indicator_set_status(_trayIndicator, APP_INDICATOR_STATUS_ACTIVE); - Libs::app_indicator_set_menu(_trayIndicator, Libs::gtk_menu_cast(_trayMenu)); - useStatusIcon = false; - } else { - DEBUG_LOG(("AppIndicator failed!")); - useAppIndicator = false; - } - } - if (useStatusIcon) { - if (Libs::gdk_init_check(0, 0)) { - if (!_trayMenu) _trayMenu = Libs::gtk_menu_new(); - if (_trayMenu) { - QFileInfo iconFile(_trayIconImageFile()); - if (iconFile.exists()) { - QByteArray path = QFile::encodeName(iconFile.absoluteFilePath()); - _trayIcon = Libs::gtk_status_icon_new_from_file(path.constData()); - } else { - loadPixbuf(_trayIconImageGen()); - _trayIcon = Libs::gtk_status_icon_new_from_pixbuf(_trayPixbuf); - } - if (_trayIcon) { - LOG(("Tray Icon: Using GTK status tray icon.")); - - Libs::g_signal_connect_helper(_trayIcon, "popup-menu", GCallback(_trayIconPopup), _trayMenu); - Libs::g_signal_connect_helper(_trayIcon, "activate", GCallback(_trayIconActivate), _trayMenu); - Libs::g_signal_connect_helper(_trayIcon, "size-changed", GCallback(_trayIconResized), _trayMenu); - - Libs::gtk_status_icon_set_title(_trayIcon, AppName.c_str()); - Libs::gtk_status_icon_set_tooltip_text(_trayIcon, AppName.c_str()); - Libs::gtk_status_icon_set_visible(_trayIcon, true); - } else { - useStatusIcon = false; - } - } else { - useStatusIcon = false; - } - } else { - useStatusIcon = false; - } - } - if (!useStatusIcon && !useAppIndicator) { - LOG(("Tray Icon: Not able to use any tray icon :(")); - if (_trayMenu) { - Libs::g_object_ref_sink(_trayMenu); - Libs::g_object_unref(_trayMenu); - _trayMenu = nullptr; - } - } - cSetSupportTray(useAppIndicator); - if (useStatusIcon) { - Libs::g_idle_add((GSourceFunc)_trayIconCheck, 0); - _psCheckStatusIconTimer.start(100); - } else { - workmodeUpdated(Global::WorkMode().value()); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } void MainWindow::psFirstShow() { psCreateTrayIcon(); -#if !defined(TDESKTOP_DISABLE_GTK_INTEGRATION) && !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION) +#if !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION) if (useUnityCount) { _psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop"); if (_psUnityLauncherEntry) { @@ -567,7 +282,7 @@ void MainWindow::psFirstShow() { } else { LOG(("Not using Unity Launcher count.")); } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION && !TDESKTOP_DISABLE_GTK_INTEGRATION +#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION psUpdateMargins(); @@ -602,31 +317,12 @@ void MainWindow::psUpdateMargins() { } MainWindow::~MainWindow() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (_trayIcon) { - Libs::g_object_unref(_trayIcon); - _trayIcon = nullptr; - } - if (_trayPixbuf) { - Libs::g_object_unref(_trayPixbuf); - _trayPixbuf = nullptr; - } - if (_trayMenu) { - Libs::g_object_ref_sink(_trayMenu); - Libs::g_object_unref(_trayMenu); - _trayMenu = nullptr; - } - if (_trayIndicator) { - Libs::g_object_unref(_trayIndicator); - _trayIndicator = nullptr; - } #ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION if (_psUnityLauncherEntry) { Libs::g_object_unref(_psUnityLauncherEntry); _psUnityLauncherEntry = nullptr; } #endif // ! TDESKTOP_DISABLE_UNITY_INTEGRATION -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } } // namespace Platform diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp index 435ee000c..9b839005d 100644 --- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp @@ -29,535 +29,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Platform { namespace Notifications { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -namespace { - -bool LibNotifyLoaded() { - return (Libs::notify_init != nullptr) - && (Libs::notify_uninit != nullptr) - && (Libs::notify_is_initted != nullptr) -// && (Libs::notify_get_app_name != nullptr) -// && (Libs::notify_set_app_name != nullptr) - && (Libs::notify_get_server_caps != nullptr) - && (Libs::notify_get_server_info != nullptr) - && (Libs::notify_notification_new != nullptr) -// && (Libs::notify_notification_update != nullptr) - && (Libs::notify_notification_show != nullptr) -// && (Libs::notify_notification_set_app_name != nullptr) - && (Libs::notify_notification_set_timeout != nullptr) -// && (Libs::notify_notification_set_category != nullptr) -// && (Libs::notify_notification_set_urgency != nullptr) -// && (Libs::notify_notification_set_icon_from_pixbuf != nullptr) - && (Libs::notify_notification_set_image_from_pixbuf != nullptr) -// && (Libs::notify_notification_set_hint != nullptr) -// && (Libs::notify_notification_set_hint_int32 != nullptr) -// && (Libs::notify_notification_set_hint_uint32 != nullptr) -// && (Libs::notify_notification_set_hint_double != nullptr) - && (Libs::notify_notification_set_hint_string != nullptr) -// && (Libs::notify_notification_set_hint_byte != nullptr) -// && (Libs::notify_notification_set_hint_byte_array != nullptr) -// && (Libs::notify_notification_clear_hints != nullptr) - && (Libs::notify_notification_add_action != nullptr) - && (Libs::notify_notification_clear_actions != nullptr) - && (Libs::notify_notification_close != nullptr) - && (Libs::notify_notification_get_closed_reason != nullptr) - && (Libs::g_object_ref_sink != nullptr) - && (Libs::g_object_unref != nullptr) - && (Libs::g_list_free_full != nullptr) - && (Libs::g_error_free != nullptr) - && (Libs::g_signal_connect_data != nullptr) - && (Libs::g_signal_handler_disconnect != nullptr) -// && (Libs::gdk_pixbuf_new_from_data != nullptr) - && (Libs::gdk_pixbuf_new_from_file != nullptr); -} - -QString escapeHtml(const QString &text) { - auto result = QString(); - auto copyFrom = 0, textSize = text.size(); - auto data = text.constData(); - for (auto i = 0; i != textSize; ++i) { - auto ch = data[i]; - if (ch == '<' || ch == '>' || ch == '&') { - if (!copyFrom) { - result.reserve(textSize * 5); - } - if (i > copyFrom) { - result.append(data + copyFrom, i - copyFrom); - } - switch (ch.unicode()) { - case '<': result.append(qstr("<")); break; - case '>': result.append(qstr(">")); break; - case '&': result.append(qstr("&")); break; - } - copyFrom = i + 1; - } - } - if (copyFrom > 0) { - result.append(data + copyFrom, textSize - copyFrom); - return result; - } - return text; -} - -class NotificationData { -public: - NotificationData(const std::shared_ptr<Manager*> &guarded, const QString &title, const QString &body, const QStringList &capabilities, PeerId peerId, MsgId msgId) - : _data(Libs::notify_notification_new(title.toUtf8().constData(), body.toUtf8().constData(), nullptr)) { - if (valid()) { - init(guarded, capabilities, peerId, msgId); - } - } - bool valid() const { - return (_data != nullptr); - } - NotificationData(const NotificationData &other) = delete; - NotificationData &operator=(const NotificationData &other) = delete; - NotificationData(NotificationData &&other) = delete; - NotificationData &operator=(NotificationData &&other) = delete; - - void setImage(const QString &imagePath) { - auto imagePathNative = QFile::encodeName(imagePath); - if (auto pixbuf = Libs::gdk_pixbuf_new_from_file(imagePathNative.constData(), nullptr)) { - Libs::notify_notification_set_image_from_pixbuf(_data, pixbuf); - Libs::g_object_unref(Libs::g_object_cast(pixbuf)); - } - } - bool show() { - if (valid()) { - GError *error = nullptr; - Libs::notify_notification_show(_data, &error); - if (!error) { - return true; - } - - logError(error); - } - return false; - } - - bool close() { - if (valid()) { - GError *error = nullptr; - Libs::notify_notification_close(_data, &error); - if (!error) { - return true; - } - - logError(error); - } - return false; - } - - ~NotificationData() { - if (valid()) { -// if (_handlerId > 0) { -// Libs::g_signal_handler_disconnect(Libs::g_object_cast(_data), _handlerId); -// } -// Libs::notify_notification_clear_actions(_data); - Libs::g_object_unref(Libs::g_object_cast(_data)); - } - } - -private: - void init(const std::shared_ptr<Manager*> &guarded, const QStringList &capabilities, PeerId peerId, MsgId msgId) { - if (capabilities.contains(qsl("append"))) { - Libs::notify_notification_set_hint_string(_data, "append", "true"); - } else if (capabilities.contains(qsl("x-canonical-append"))) { - Libs::notify_notification_set_hint_string(_data, "x-canonical-append", "true"); - } - - auto signalReceiver = Libs::g_object_cast(_data); - auto signalHandler = G_CALLBACK(NotificationData::notificationClosed); - auto signalName = "closed"; - auto signalDataFreeMethod = &NotificationData::notificationDataFreeClosure; - auto signalData = new NotificationDataStruct(guarded, peerId, msgId); - _handlerId = Libs::g_signal_connect_helper(signalReceiver, signalName, signalHandler, signalData, signalDataFreeMethod); - - Libs::notify_notification_set_timeout(_data, Libs::NOTIFY_EXPIRES_DEFAULT); - - if ((*guarded)->hasActionsSupport()) { - auto label = lang(lng_notification_reply).toUtf8(); - auto actionReceiver = _data; - auto actionHandler = &NotificationData::notificationClicked; - auto actionLabel = label.constData(); - auto actionName = "default"; - auto actionDataFreeMethod = &NotificationData::notificationDataFree; - auto actionData = new NotificationDataStruct(guarded, peerId, msgId); - Libs::notify_notification_add_action(actionReceiver, actionName, actionLabel, actionHandler, actionData, actionDataFreeMethod); - } - } - - void logError(GError *error) { - LOG(("LibNotify Error: domain %1, code %2, message '%3'").arg(error->domain).arg(error->code).arg(QString::fromUtf8(error->message))); - Libs::g_error_free(error); - } - - struct NotificationDataStruct { - NotificationDataStruct(const std::shared_ptr<Manager*> &guarded, PeerId peerId, MsgId msgId) - : weak(guarded) - , peerId(peerId) - , msgId(msgId) { - } - - std::weak_ptr<Manager*> weak; - PeerId peerId = 0; - MsgId msgId = 0; - }; - static void performOnMainQueue(NotificationDataStruct *data, base::lambda_once<void(Manager *manager)> task) { - base::TaskQueue::Main().Put([weak = data->weak, task = std::move(task)]() mutable { - if (auto strong = weak.lock()) { - task(*strong); - } - }); - } - static void notificationDataFree(gpointer data) { - auto notificationData = static_cast<NotificationDataStruct*>(data); - delete notificationData; - } - static void notificationDataFreeClosure(gpointer data, GClosure *closure) { - auto notificationData = static_cast<NotificationDataStruct*>(data); - delete notificationData; - } - static void notificationClosed(Libs::NotifyNotification *notification, gpointer data) { - auto closedReason = Libs::notify_notification_get_closed_reason(notification); - auto notificationData = static_cast<NotificationDataStruct*>(data); - performOnMainQueue(notificationData, [peerId = notificationData->peerId, msgId = notificationData->msgId](Manager *manager) { - manager->clearNotification(peerId, msgId); - }); - } - static void notificationClicked(Libs::NotifyNotification *notification, char *action, gpointer data) { - auto notificationData = static_cast<NotificationDataStruct*>(data); - performOnMainQueue(notificationData, [peerId = notificationData->peerId, msgId = notificationData->msgId](Manager *manager) { - manager->notificationActivated(peerId, msgId); - }); - } - - Libs::NotifyNotification *_data = nullptr; - gulong _handlerId = 0; - -}; - -using Notification = QSharedPointer<NotificationData>; - -QString GetServerName() { - if (!LibNotifyLoaded()) { - return QString(); - } - if (!Libs::notify_is_initted() && !Libs::notify_init(AppName.c_str())) { - LOG(("LibNotify Error: failed to init!")); - return QString(); - } - - gchar *name = nullptr; - auto guard = gsl::finally([&name] { - if (name) Libs::g_free(name); - }); - - if (!Libs::notify_get_server_info(&name, nullptr, nullptr, nullptr)) { - LOG(("LibNotify Error: could not get server name!")); - return QString(); - } - if (!name) { - LOG(("LibNotify Error: successfully got empty server name!")); - return QString(); - } - - auto result = QString::fromUtf8(static_cast<const char*>(name)); - LOG(("Notifications Server: %1").arg(result)); - - return result; -} - -auto LibNotifyServerName = QString(); - -} // namespace -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION bool Supported() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - static auto Checked = false; - if (!Checked) { - Checked = true; - LibNotifyServerName = GetServerName(); - } - - return !LibNotifyServerName.isEmpty(); -#else return false; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (Global::NativeNotifications() && Supported()) { - return std::make_unique<Manager>(system); - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION return nullptr; } void Finish() { -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION - if (Libs::notify_is_initted && Libs::notify_uninit) { - if (Libs::notify_is_initted()) { - Libs::notify_uninit(); - } - } -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION } -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -class Manager::Private { -public: - using Type = Window::Notifications::CachedUserpics::Type; - explicit Private(Type type) - : _cachedUserpics(type) { - } - - void init(Manager *manager); - - void showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton); - void clearAll(); - void clearFromHistory(History *history); - void clearNotification(PeerId peerId, MsgId msgId); - - bool hasPoorSupport() const { - return _poorSupported; - } - bool hasActionsSupport() const { - return _actionsSupported; - } - - ~Private(); - -private: - QString escapeNotificationText(const QString &text) const; - void showNextNotification(); - - struct QueuedNotification { - PeerData *peer = nullptr; - MsgId msgId = 0; - QString title; - QString body; - bool hideNameAndPhoto = false; - }; - - QString _serverName; - QStringList _capabilities; - - using QueuedNotifications = QList<QueuedNotification>; - QueuedNotifications _queuedNotifications; - - using Notifications = QMap<PeerId, QMap<MsgId, Notification>>; - Notifications _notifications; - - Window::Notifications::CachedUserpics _cachedUserpics; - bool _actionsSupported = false; - bool _markupSupported = false; - bool _poorSupported = false; - - std::shared_ptr<Manager*> _guarded; - -}; -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - -#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION -void Manager::Private::init(Manager *manager) { - _guarded = std::make_shared<Manager*>(manager); - - if (auto capabilities = Libs::notify_get_server_caps()) { - for (auto capability = capabilities; capability; capability = capability->next) { - auto capabilityText = QString::fromUtf8(static_cast<const char*>(capability->data)); - _capabilities.push_back(capabilityText); - } - Libs::g_list_free_full(capabilities, g_free); - - LOG(("LibNotify capabilities: %1").arg(_capabilities.join(qstr(", ")))); - if (_capabilities.contains(qsl("actions"))) { - _actionsSupported = true; - } else if (_capabilities.contains(qsl("body-markup"))) { - _markupSupported = true; - } - } else { - LOG(("LibNotify Error: could not get capabilities!")); - } - - // Unity and other Notify OSD users handle desktop notifications - // extremely poor, even without the ability to close() them. - _serverName = LibNotifyServerName; - Assert(!_serverName.isEmpty()); - if (_serverName == qstr("notify-osd")) { -// _poorSupported = true; - _actionsSupported = false; - } -} - -QString Manager::Private::escapeNotificationText(const QString &text) const { - return _markupSupported ? escapeHtml(text) : text; -} - -void Manager::Private::showNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) { - auto titleText = escapeNotificationText(title); - auto subtitleText = escapeNotificationText(subtitle); - auto msgText = escapeNotificationText(msg); - if (_markupSupported && !subtitleText.isEmpty()) { - subtitleText = qstr("<b>") + subtitleText + qstr("</b>"); - } - auto bodyText = subtitleText.isEmpty() ? msgText : (subtitleText + '\n' + msgText); - - QueuedNotification notification; - notification.peer = peer; - notification.msgId = msgId; - notification.title = titleText; - notification.body = bodyText; - notification.hideNameAndPhoto = hideNameAndPhoto; - _queuedNotifications.push_back(notification); - - showNextNotification(); -} - -void Manager::Private::showNextNotification() { - // Show only one notification at a time in Unity / Notify OSD. - if (_poorSupported) { - for (auto b = _notifications.begin(); !_notifications.isEmpty() && b->isEmpty();) { - _notifications.erase(b); - } - if (!_notifications.isEmpty()) { - return; - } - } - - QueuedNotification data; - while (!_queuedNotifications.isEmpty()) { - data = _queuedNotifications.front(); - _queuedNotifications.pop_front(); - if (data.peer) { - break; - } - } - if (!data.peer) { - return; - } - - auto peerId = data.peer->id; - auto msgId = data.msgId; - auto notification = MakeShared<NotificationData>(_guarded, data.title, data.body, _capabilities, peerId, msgId); - if (!notification->valid()) { - return; - } - - StorageKey key; - if (data.hideNameAndPhoto) { - key = StorageKey(0, 0); - } else { - key = data.peer->userpicUniqueKey(); - } - notification->setImage(_cachedUserpics.get(key, data.peer)); - - auto i = _notifications.find(peerId); - if (i != _notifications.cend()) { - auto j = i->find(msgId); - if (j != i->cend()) { - auto oldNotification = j.value(); - i->erase(j); - oldNotification->close(); - i = _notifications.find(peerId); - } - } - if (i == _notifications.cend()) { - i = _notifications.insert(peerId, QMap<MsgId, Notification>()); - } - _notifications[peerId].insert(msgId, notification); - if (!notification->show()) { - i = _notifications.find(peerId); - if (i != _notifications.cend()) { - i->remove(msgId); - if (i->isEmpty()) _notifications.erase(i); - } - showNextNotification(); - } -} - -void Manager::Private::clearAll() { - _queuedNotifications.clear(); - - auto temp = base::take(_notifications); - for_const (auto ¬ifications, temp) { - for_const (auto notification, notifications) { - notification->close(); - } - } -} - -void Manager::Private::clearFromHistory(History *history) { - for (auto i = _queuedNotifications.begin(); i != _queuedNotifications.end();) { - if (i->peer == history->peer) { - i = _queuedNotifications.erase(i); - } else { - ++i; - } - } - - auto i = _notifications.find(history->peer->id); - if (i != _notifications.cend()) { - auto temp = base::take(i.value()); - _notifications.erase(i); - - for_const (auto notification, temp) { - notification->close(); - } - } - - showNextNotification(); -} - -void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) { - auto i = _notifications.find(peerId); - if (i != _notifications.cend()) { - i.value().remove(msgId); - if (i.value().isEmpty()) { - _notifications.erase(i); - } - } - - showNextNotification(); -} - -Manager::Private::~Private() { - clearAll(); -} - -Manager::Manager(Window::Notifications::System *system) : NativeManager(system) -, _private(std::make_unique<Private>(Private::Type::Rounded)) { - _private->init(this); -} - -void Manager::clearNotification(PeerId peerId, MsgId msgId) { - _private->clearNotification(peerId, msgId); -} - -bool Manager::hasPoorSupport() const { - return _private->hasPoorSupport(); -} - -bool Manager::hasActionsSupport() const { - return _private->hasActionsSupport(); -} - -Manager::~Manager() = default; - -void Manager::doShowNativeNotification(PeerData *peer, MsgId msgId, const QString &title, const QString &subtitle, const QString &msg, bool hideNameAndPhoto, bool hideReplyButton) { - _private->showNotification(peer, msgId, title, subtitle, msg, hideNameAndPhoto, hideReplyButton); -} - -void Manager::doClearAllFast() { - _private->clearAll(); -} - -void Manager::doClearFromHistory(History *history) { - _private->clearFromHistory(history); -} -#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION - } // namespace Notifications } // namespace Platform