mirror of https://github.com/procxx/kepka.git
				
				
				
			Completely drop GTK dialogs. Use native instead.
Also this commit will remove libnotify support. Signed-off-by: Vitaly Zaitsev <vitaly@easycoding.org>
This commit is contained in:
		
							parent
							
								
									1ab8aa2463
								
							
						
					
					
						commit
						dbb0030893
					
				| 
						 | 
					@ -592,7 +592,7 @@ add_definitions(-DAL_ALEXT_PROTOTYPES)
 | 
				
			||||||
add_definitions(-DTGVOIP_USE_CXX11_LIB)
 | 
					add_definitions(-DTGVOIP_USE_CXX11_LIB)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
add_definitions(-DTDESKTOP_DISABLE_CRASH_REPORTS)
 | 
					add_definitions(-DTDESKTOP_DISABLE_CRASH_REPORTS)
 | 
				
			||||||
add_definitions(-DTDESKTOP_DISABLE_GTK_INTEGRATION) # Linux only
 | 
					add_definitions(-DTDESKTOP_DISABLE_UNITY_INTEGRATION) # Linux only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (LINUX)
 | 
					if (LINUX)
 | 
				
			||||||
    add_definitions(-D_REENTRANT)
 | 
					    add_definitions(-D_REENTRANT)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,222 +95,15 @@ void UnsafeShowInFolder(const QString &filepath) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace FileDialog {
 | 
					namespace FileDialog {
 | 
				
			||||||
namespace {
 | 
					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;
 | 
					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
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Get(QStringList &files, QByteArray &remoteContent, const QString &caption, const QString &filter, Type type, QString startFile) {
 | 
					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);
 | 
						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 {
 | 
					namespace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char *filterRegExp =
 | 
					const char *filterRegExp =
 | 
				
			||||||
| 
						 | 
					@ -328,311 +121,5 @@ QStringList cleanFilterList(const QString &filter) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // 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 FileDialog
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,10 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#undef signals
 | 
					#undef signals
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
#include <gtk/gtk.h>
 | 
					 | 
				
			||||||
#include <gdk/gdk.h>
 | 
					 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
#define signals public
 | 
					#define signals public
 | 
				
			||||||
} // extern "C"
 | 
					} // extern "C"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,114 +66,5 @@ inline void InitLastPath() {
 | 
				
			||||||
	::FileDialog::internal::InitLastPathDefault();
 | 
						::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 FileDialog
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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
 | 
					Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | 
				
			||||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
					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
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,21 +22,3 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <QtCore/QObject>
 | 
					#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
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,81 +43,5 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // 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 Libs
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,115 +19,3 @@ Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
 | 
				
			||||||
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
					Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
#pragma once
 | 
					#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
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,262 +44,17 @@ bool loadLibrary(QLibrary &lib, const char *name, int version) {
 | 
				
			||||||
    return false;
 | 
					    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
 | 
					} // 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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
f_unity_launcher_entry_set_count unity_launcher_entry_set_count = nullptr;
 | 
					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_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;
 | 
					f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id = nullptr;
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
void start() {
 | 
					void start() {
 | 
				
			||||||
	DEBUG_LOG(("Loading libraries"));
 | 
						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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
	if (DesktopEnvironment::TryUnityCounter()) {
 | 
						if (DesktopEnvironment::TryUnityCounter()) {
 | 
				
			||||||
| 
						 | 
					@ -311,11 +66,6 @@ void start() {
 | 
				
			||||||
		load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
 | 
							load(lib_unity, "unity_launcher_entry_set_count_visible", unity_launcher_entry_set_count_visible);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (gtkLoaded) {
 | 
					 | 
				
			||||||
		startLibNotify();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Libs
 | 
					} // namespace Libs
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,19 +20,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
#pragma once
 | 
					#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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#include <unity/unity/unity.h>
 | 
					#include <unity/unity/unity.h>
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Platform {
 | 
					namespace Platform {
 | 
				
			||||||
namespace Libs {
 | 
					namespace Libs {
 | 
				
			||||||
| 
						 | 
					@ -54,326 +44,6 @@ bool load(QLibrary &lib, const char *name, Function &func) {
 | 
				
			||||||
	return false;
 | 
						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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value);
 | 
					typedef void (*f_unity_launcher_entry_set_count)(UnityLauncherEntry* self, gint64 value);
 | 
				
			||||||
extern f_unity_launcher_entry_set_count unity_launcher_entry_set_count;
 | 
					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);
 | 
					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;
 | 
					extern f_unity_launcher_entry_get_for_desktop_id unity_launcher_entry_get_for_desktop_id;
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Libs
 | 
					} // namespace Libs
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,51 +36,18 @@ namespace {
 | 
				
			||||||
bool noQtTrayIcon = false, tryAppIndicator = false;
 | 
					bool noQtTrayIcon = false, tryAppIndicator = false;
 | 
				
			||||||
bool useGtkBase = false, useAppIndicator = false, useStatusIcon = false, trayIconChecked = false, useUnityCount = 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;
 | 
					qint32 _trayIconSize = 22;
 | 
				
			||||||
bool _trayIconMuted = true;
 | 
					bool _trayIconMuted = true;
 | 
				
			||||||
qint32 _trayIconCount = 0;
 | 
					qint32 _trayIconCount = 0;
 | 
				
			||||||
QImage _trayIconImageBack, _trayIconImage;
 | 
					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_RED 0
 | 
				
			||||||
#define QT_GREEN 1
 | 
					#define QT_GREEN 1
 | 
				
			||||||
#define QT_BLUE 2
 | 
					#define QT_BLUE 2
 | 
				
			||||||
#define QT_ALPHA 3
 | 
					#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() {
 | 
					QImage _trayIconImageGen() {
 | 
				
			||||||
	qint32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter;
 | 
						qint32 counter = App::histories().unreadBadge(), counterSlice = (counter >= 1000) ? (1000 + (counter % 100)) : counter;
 | 
				
			||||||
| 
						 | 
					@ -139,55 +106,10 @@ QString _trayIconImageFile() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return QString();
 | 
						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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
 | 
					UnityLauncherEntry *_psUnityLauncherEntry = nullptr;
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace
 | 
					} // namespace
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,17 +122,10 @@ MainWindow::MainWindow() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool MainWindow::hasTrayIcon() const {
 | 
					bool MainWindow::hasTrayIcon() const {
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
	return trayIcon || ((useAppIndicator || (useStatusIcon && trayIconChecked)) && (Global::WorkMode().value() != dbiwmWindowOnly));
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	return trayIcon;
 | 
						return trayIcon;
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::psStatusIconCheck() {
 | 
					void MainWindow::psStatusIconCheck() {
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
	_trayIconCheck(0);
 | 
					 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
	if (cSupportTray() || !--_psCheckStatusIconLeft) {
 | 
						if (cSupportTray() || !--_psCheckStatusIconLeft) {
 | 
				
			||||||
		_psCheckStatusIconTimer.stop();
 | 
							_psCheckStatusIconTimer.stop();
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -221,31 +136,6 @@ void MainWindow::psShowTrayMenu() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::psTrayMenuUpdated() {
 | 
					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() {
 | 
					void MainWindow::psSetupTrayIcon() {
 | 
				
			||||||
| 
						 | 
					@ -289,13 +179,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (mode == dbiwmWindowOnly) {
 | 
						if (mode == dbiwmWindowOnly) {
 | 
				
			||||||
		if (noQtTrayIcon) {
 | 
							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 {
 | 
							} else {
 | 
				
			||||||
			if (trayIcon) {
 | 
								if (trayIcon) {
 | 
				
			||||||
				trayIcon->setContextMenu(0);
 | 
									trayIcon->setContextMenu(0);
 | 
				
			||||||
| 
						 | 
					@ -305,13 +188,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (noQtTrayIcon) {
 | 
							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 {
 | 
							} else {
 | 
				
			||||||
			psSetupTrayIcon();
 | 
								psSetupTrayIcon();
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -319,18 +195,6 @@ void MainWindow::workmodeUpdated(DBIWorkMode mode) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::psUpdateIndicator() {
 | 
					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() {
 | 
					void MainWindow::unreadCounterChangedHook() {
 | 
				
			||||||
| 
						 | 
					@ -343,7 +207,7 @@ void MainWindow::updateIconCounters() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto counter = App::histories().unreadBadge();
 | 
						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 (_psUnityLauncherEntry) {
 | 
				
			||||||
		if (counter > 0) {
 | 
							if (counter > 0) {
 | 
				
			||||||
			Libs::unity_launcher_entry_set_count(_psUnityLauncherEntry, (counter > 9999) ? 9999 : counter);
 | 
								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);
 | 
								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) {
 | 
						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) {
 | 
						} else if (trayIcon) {
 | 
				
			||||||
		QIcon icon;
 | 
							QIcon icon;
 | 
				
			||||||
		QFileInfo iconFile(_trayIconImageFile());
 | 
							QFileInfo iconFile(_trayIconImageFile());
 | 
				
			||||||
| 
						 | 
					@ -394,61 +240,11 @@ void MainWindow::updateIconCounters() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::LibsLoaded() {
 | 
					void MainWindow::LibsLoaded() {
 | 
				
			||||||
	noQtTrayIcon = !DesktopEnvironment::TryQtTrayIcon();
 | 
						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)));
 | 
						LOG(("Tray Icon: Try Qt = %1, Prefer appindicator = %2").arg(Logs::b(!noQtTrayIcon)).arg(Logs::b(tryAppIndicator)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (noQtTrayIcon) cSetSupportTray(false);
 | 
						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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
	useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
 | 
						useUnityCount = (Libs::unity_launcher_entry_get_for_desktop_id != nullptr)
 | 
				
			||||||
			&& (Libs::unity_launcher_entry_set_count != nullptr)
 | 
								&& (Libs::unity_launcher_entry_set_count != nullptr)
 | 
				
			||||||
| 
						 | 
					@ -457,7 +253,6 @@ void MainWindow::LibsLoaded() {
 | 
				
			||||||
		DEBUG_LOG(("Unity count api loaded!"));
 | 
							DEBUG_LOG(("Unity count api loaded!"));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MainWindow::psCreateTrayIcon() {
 | 
					void MainWindow::psCreateTrayIcon() {
 | 
				
			||||||
| 
						 | 
					@ -466,92 +261,12 @@ void MainWindow::psCreateTrayIcon() {
 | 
				
			||||||
		cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable());
 | 
							cSetSupportTray(QSystemTrayIcon::isSystemTrayAvailable());
 | 
				
			||||||
		return;
 | 
							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() {
 | 
					void MainWindow::psFirstShow() {
 | 
				
			||||||
	psCreateTrayIcon();
 | 
						psCreateTrayIcon();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if !defined(TDESKTOP_DISABLE_GTK_INTEGRATION) && !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION)
 | 
					#if !defined(TDESKTOP_DISABLE_UNITY_INTEGRATION)
 | 
				
			||||||
	if (useUnityCount) {
 | 
						if (useUnityCount) {
 | 
				
			||||||
		_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
 | 
							_psUnityLauncherEntry = Libs::unity_launcher_entry_get_for_desktop_id("telegramdesktop.desktop");
 | 
				
			||||||
		if (_psUnityLauncherEntry) {
 | 
							if (_psUnityLauncherEntry) {
 | 
				
			||||||
| 
						 | 
					@ -567,7 +282,7 @@ void MainWindow::psFirstShow() {
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		LOG(("Not using Unity Launcher count."));
 | 
							LOG(("Not using Unity Launcher count."));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION && !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					#endif // !TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	psUpdateMargins();
 | 
						psUpdateMargins();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -602,31 +317,12 @@ void MainWindow::psUpdateMargins() {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MainWindow::~MainWindow() {
 | 
					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
 | 
					#ifndef TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
	if (_psUnityLauncherEntry) {
 | 
						if (_psUnityLauncherEntry) {
 | 
				
			||||||
		Libs::g_object_unref(_psUnityLauncherEntry);
 | 
							Libs::g_object_unref(_psUnityLauncherEntry);
 | 
				
			||||||
		_psUnityLauncherEntry = nullptr;
 | 
							_psUnityLauncherEntry = nullptr;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif // ! TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
					#endif // ! TDESKTOP_DISABLE_UNITY_INTEGRATION
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,535 +29,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Platform {
 | 
					namespace Platform {
 | 
				
			||||||
namespace Notifications {
 | 
					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() {
 | 
					bool Supported() {
 | 
				
			||||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
	static auto Checked = false;
 | 
					 | 
				
			||||||
	if (!Checked) {
 | 
					 | 
				
			||||||
		Checked = true;
 | 
					 | 
				
			||||||
		LibNotifyServerName = GetServerName();
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return !LibNotifyServerName.isEmpty();
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::unique_ptr<Window::Notifications::Manager> Create(Window::Notifications::System *system) {
 | 
					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;
 | 
						return nullptr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Finish() {
 | 
					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 Notifications
 | 
				
			||||||
} // namespace Platform
 | 
					} // namespace Platform
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue