Use gtk not only to get image from clipboard, but also to set

This commit is contained in:
Ilya Fedin 2020-12-02 10:16:25 +04:00 committed by John Preston
parent 61b7b5d03b
commit f88c132c96
15 changed files with 112 additions and 21 deletions

View File

@ -80,7 +80,7 @@ auto ListFromMimeData(not_null<const QMimeData*> data) {
if (result.error == Error::None) {
return result;
} else if (data->hasImage()) {
auto image = Platform::GetImageFromClipboard();
auto image = Platform::GetClipboardImage();
if (image.isNull()) {
image = qvariant_cast<QImage>(data->imageData());
}

View File

@ -767,7 +767,7 @@ bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
if (result.error == Ui::PreparedList::Error::None) {
return result;
} else if (data->hasImage()) {
auto image = Platform::GetImageFromClipboard();
auto image = Platform::GetClipboardImage();
if (image.isNull()) {
image = qvariant_cast<QImage>(data->imageData());
}

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/message_field.h"
#include "boxes/sticker_set_box.h"
#include "base/platform/base_platform_info.h"
#include "platform/platform_specific.h"
#include "mainwindow.h"
#include "mainwidget.h"
#include "core/application.h"
@ -1219,7 +1220,9 @@ void InnerWidget::copyContextImage(not_null<PhotoData*> photo) {
}
const auto image = media->image(Data::PhotoSize::Large)->original();
QGuiApplication::clipboard()->setImage(image);
if (!Platform::SetClipboardImage(image)) {
QGuiApplication::clipboard()->setImage(image);
}
}
void InnerWidget::copySelectedText() {

View File

@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/sticker_set_box.h"
#include "chat_helpers/message_field.h"
#include "history/history_widget.h"
#include "platform/platform_specific.h"
#include "base/platform/base_platform_info.h"
#include "base/unixtime.h"
#include "mainwindow.h"
@ -1899,7 +1900,9 @@ void HistoryInner::copyContextImage(not_null<PhotoData*> photo) {
}
const auto image = media->image(Data::PhotoSize::Large)->original();
QGuiApplication::clipboard()->setImage(image);
if (!Platform::SetClipboardImage(image)) {
QGuiApplication::clipboard()->setImage(image);
}
}
void HistoryInner::showStickerPackInfo(not_null<DocumentData*> document) {

View File

@ -4335,7 +4335,7 @@ bool HistoryWidget::confirmSendingFiles(
}
if (hasImage) {
auto image = Platform::GetImageFromClipboard();
auto image = Platform::GetClipboardImage();
if (image.isNull()) {
image = qvariant_cast<QImage>(data->imageData());
}

View File

@ -39,6 +39,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_scheduled_messages.h"
#include "core/file_utilities.h"
#include "base/platform/base_platform_info.h"
#include "platform/platform_specific.h"
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "lang/lang_keys.h"
@ -125,7 +126,9 @@ void CopyImage(not_null<PhotoData*> photo) {
}
const auto image = media->image(Data::PhotoSize::Large)->original();
QGuiApplication::clipboard()->setImage(image);
if (!Platform::SetClipboardImage(image)) {
QGuiApplication::clipboard()->setImage(image);
}
}
void ShowStickerPackInfo(

View File

@ -603,7 +603,7 @@ bool RepliesWidget::confirmSendingFiles(
}
if (hasImage) {
auto image = Platform::GetImageFromClipboard();
auto image = Platform::GetClipboardImage();
if (image.isNull()) {
image = qvariant_cast<QImage>(data->imageData());
}

View File

@ -335,7 +335,7 @@ bool ScheduledWidget::confirmSendingFiles(
}
if (hasImage) {
auto image = Platform::GetImageFromClipboard();
auto image = Platform::GetClipboardImage();
if (image.isNull()) {
image = qvariant_cast<QImage>(data->imageData());
}

View File

@ -50,6 +50,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_peer_menu.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "platform/platform_specific.h"
#include "base/platform/base_platform_info.h"
#include "base/unixtime.h"
#include "main/main_account.h"
@ -1652,13 +1653,18 @@ void OverlayWidget::onOverview() {
void OverlayWidget::onCopy() {
_dropdown->hideAnimated(Ui::DropdownMenu::HideOption::IgnoreShow);
if (_document) {
QGuiApplication::clipboard()->setImage(videoShown()
const auto image = videoShown()
? transformVideoFrame(videoFrame())
: transformStaticContent(_staticContent));
: transformStaticContent(_staticContent);
if (!Platform::SetClipboardImage(image)) {
QGuiApplication::clipboard()->setImage(image);
}
} else if (_photo && _photoMedia->loaded()) {
const auto image = _photoMedia->image(
Data::PhotoSize::Large)->original();
QGuiApplication::clipboard()->setImage(image);
if (!Platform::SetClipboardImage(image)) {
QGuiApplication::clipboard()->setImage(image);
}
}
}

View File

@ -73,10 +73,6 @@ bool setupGtkBase(QLibrary &lib_gtk) {
if (!LOAD_SYMBOL(lib_gtk, "gtk_widget_get_type", gtk_widget_get_type)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_get", gtk_clipboard_get)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_store", gtk_clipboard_store)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_selection_data_free", gtk_selection_data_free)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_file_chooser_dialog_new", gtk_file_chooser_dialog_new)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_file_chooser_get_type", gtk_file_chooser_get_type)) return false;
if (!LOAD_SYMBOL(lib_gtk, "gtk_image_get_type", gtk_image_get_type)) return false;
@ -215,6 +211,7 @@ f_gtk_widget_destroy gtk_widget_destroy = nullptr;
f_gtk_widget_get_type gtk_widget_get_type = nullptr;
f_gtk_clipboard_get gtk_clipboard_get = nullptr;
f_gtk_clipboard_store gtk_clipboard_store = nullptr;
f_gtk_clipboard_set_image gtk_clipboard_set_image = nullptr;
f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents = nullptr;
f_gtk_clipboard_wait_for_image gtk_clipboard_wait_for_image = nullptr;
f_gtk_selection_data_targets_include_image gtk_selection_data_targets_include_image = nullptr;
@ -257,6 +254,7 @@ 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_gdk_atom_intern gdk_atom_intern = nullptr;
f_gdk_pixbuf_new_from_data gdk_pixbuf_new_from_data = nullptr;
f_gdk_pixbuf_new_from_file_at_size gdk_pixbuf_new_from_file_at_size = nullptr;
f_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha = nullptr;
f_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels = nullptr;
@ -296,6 +294,7 @@ void start() {
}
if (gtkLoaded) {
LOAD_SYMBOL(lib_gtk, "gdk_pixbuf_new_from_data", gdk_pixbuf_new_from_data);
LOAD_SYMBOL(lib_gtk, "gdk_pixbuf_new_from_file_at_size", gdk_pixbuf_new_from_file_at_size);
LOAD_SYMBOL(lib_gtk, "gdk_pixbuf_get_has_alpha", gdk_pixbuf_get_has_alpha);
LOAD_SYMBOL(lib_gtk, "gdk_pixbuf_get_pixels", gdk_pixbuf_get_pixels);
@ -305,6 +304,12 @@ void start() {
internal::GdkHelperLoad(lib_gtk);
LOAD_SYMBOL(lib_gtk, "gtk_clipboard_set_image", gtk_clipboard_set_image);
LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents);
LOAD_SYMBOL(lib_gtk, "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image);
LOAD_SYMBOL(lib_gtk, "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image);
LOAD_SYMBOL(lib_gtk, "gtk_selection_data_free", gtk_selection_data_free);
LOAD_SYMBOL(lib_gtk, "gtk_dialog_get_widget_for_response", gtk_dialog_get_widget_for_response);
LOAD_SYMBOL(lib_gtk, "gtk_button_set_label", gtk_button_set_label);
LOAD_SYMBOL(lib_gtk, "gtk_button_get_type", gtk_button_get_type);

View File

@ -88,6 +88,9 @@ 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 void (*f_gtk_clipboard_set_image)(::GtkClipboard *clipboard, GdkPixbuf *pixbuf);
extern f_gtk_clipboard_set_image gtk_clipboard_set_image;
typedef GtkSelectionData* (*f_gtk_clipboard_wait_for_contents)(::GtkClipboard *clipboard, GdkAtom target);
extern f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents;
@ -268,6 +271,9 @@ extern f_gtk_dialog_run gtk_dialog_run;
typedef GdkAtom (*f_gdk_atom_intern)(const gchar *atom_name, gboolean only_if_exists);
extern f_gdk_atom_intern gdk_atom_intern;
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_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;

View File

@ -325,7 +325,7 @@ bool GenerateDesktopFile(
}
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
bool GetImageFromClipboardSupported() {
bool GetClipboardImageSupported() {
return (Libs::gtk_clipboard_wait_for_contents != nullptr)
&& (Libs::gtk_clipboard_wait_for_image != nullptr)
&& (Libs::gtk_selection_data_targets_include_image != nullptr)
@ -337,6 +337,11 @@ bool GetImageFromClipboardSupported() {
&& (Libs::gdk_pixbuf_get_has_alpha != nullptr)
&& (Libs::gdk_atom_intern != nullptr);
}
bool SetClipboardImageSupported() {
return (Libs::gtk_clipboard_set_image != nullptr)
&& (Libs::gdk_pixbuf_new_from_data != nullptr);
}
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
uint XCBMoveResizeFromEdges(Qt::Edges edges) {
@ -729,11 +734,11 @@ QString GetIconName() {
return Result;
}
QImage GetImageFromClipboard() {
QImage GetClipboardImage() {
QImage data;
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (!GetImageFromClipboardSupported() || !Libs::GtkClipboard()) {
if (!GetClipboardImageSupported() || !Libs::GtkClipboard()) {
return data;
}
@ -767,6 +772,57 @@ QImage GetImageFromClipboard() {
return data;
}
bool SetClipboardImage(const QImage &image) {
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (!SetClipboardImageSupported()
|| !Libs::GtkClipboard()
|| image.isNull()) {
return false;
}
const auto convertedImage = [&] {
if (image.hasAlphaChannel()) {
if (image.format() != QImage::Format_RGBA8888) {
return image.convertToFormat(QImage::Format_RGBA8888);
}
} else {
if (image.format() != QImage::Format_RGB888) {
return image.convertToFormat(QImage::Format_RGB888);
}
}
return image;
}();
auto imageBuf = reinterpret_cast<guchar*>(
malloc(convertedImage.sizeInBytes()));
memcpy(
imageBuf,
convertedImage.constBits(),
convertedImage.sizeInBytes());
auto imagePixbuf = Libs::gdk_pixbuf_new_from_data(
imageBuf,
GDK_COLORSPACE_RGB,
convertedImage.hasAlphaChannel(),
8,
convertedImage.width(),
convertedImage.height(),
convertedImage.bytesPerLine(),
[](guchar *pixels, gpointer data) {
free(pixels);
},
nullptr);
Libs::gtk_clipboard_set_image(Libs::GtkClipboard(), imagePixbuf);
g_object_unref(imagePixbuf);
return true;
#else // !TDESKTOP_DISABLE_GTK_INTEGRATION
return false;
#endif // TDESKTOP_DISABLE_GTK_INTEGRATION
}
std::optional<bool> IsDarkMode() {
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
if (Libs::GtkSettingSupported() && Libs::GtkLoaded()) {

View File

@ -18,10 +18,14 @@ namespace Platform {
[[nodiscard]] bool IsDarkMenuBar();
inline QImage GetImageFromClipboard() {
inline QImage GetClipboardImage() {
return {};
}
inline bool SetClipboardImage(const QImage &image) {
return false;
}
inline bool StartSystemMove(QWindow *window) {
return false;
}

View File

@ -41,7 +41,8 @@ void IgnoreApplicationActivationRightNow();
bool AutostartSupported();
bool TrayIconSupported();
bool SkipTaskbarSupported();
QImage GetImageFromClipboard();
QImage GetClipboardImage();
bool SetClipboardImage(const QImage &image);
bool StartSystemMove(QWindow *window);
bool StartSystemResize(QWindow *window, Qt::Edges edges);
bool ShowWindowMenu(QWindow *window);

View File

@ -22,10 +22,14 @@ inline void SetWatchingMediaKeys(bool watching) {
inline void IgnoreApplicationActivationRightNow() {
}
inline QImage GetImageFromClipboard() {
inline QImage GetClipboardImage() {
return {};
}
inline bool SetClipboardImage(const QImage &image) {
return false;
}
inline bool StartSystemMove(QWindow *window) {
return false;
}