mirror of
https://github.com/kotatogram/kotatogram-desktop
synced 2025-08-31 06:35:14 +00:00
Merge remote-tracking branch 'tdesktop/dev' into dev
This commit is contained in:
@@ -72,10 +72,10 @@ bool GdkHelperLoadGtk3(QLibrary &lib) {
|
||||
|
||||
void GdkHelperLoad(QLibrary &lib) {
|
||||
gdk_helper_loaded = GtkLoaded::GtkNone;
|
||||
if (GdkHelperLoadGtk2(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk2;
|
||||
} else if (GdkHelperLoadGtk3(lib)) {
|
||||
if (GdkHelperLoadGtk3(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk3;
|
||||
} else if (GdkHelperLoadGtk2(lib)) {
|
||||
gdk_helper_loaded = GtkLoaded::Gtk2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -69,24 +69,19 @@ void gtkMessageHandler(
|
||||
bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
if (!load(lib_gtk, "gtk_init_check", gtk_init_check)) return false;
|
||||
if (!load(lib_gtk, "gtk_settings_get_default", gtk_settings_get_default)) 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_clipboard_wait_for_contents", gtk_clipboard_wait_for_contents)) return false;
|
||||
if (!load(lib_gtk, "gtk_clipboard_wait_for_image", gtk_clipboard_wait_for_image)) return false;
|
||||
if (!load(lib_gtk, "gtk_selection_data_targets_include_image", gtk_selection_data_targets_include_image)) return false;
|
||||
if (!load(lib_gtk, "gtk_selection_data_free", gtk_selection_data_free)) 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;
|
||||
@@ -122,22 +117,23 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
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_get", g_object_get)) 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;
|
||||
|
||||
if (!load(lib_gtk, "g_log_set_handler", g_log_set_handler)) return false;
|
||||
if (!load(lib_gtk, "g_log_default_handler", g_log_default_handler)) return false;
|
||||
|
||||
if (!load(lib_gtk, "gdk_atom_intern", gdk_atom_intern)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_has_alpha", gdk_pixbuf_get_has_alpha)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_pixels", gdk_pixbuf_get_pixels)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_width", gdk_pixbuf_get_width)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_height", gdk_pixbuf_get_height)) return false;
|
||||
if (!load(lib_gtk, "gdk_pixbuf_get_rowstride", gdk_pixbuf_get_rowstride)) return false;
|
||||
|
||||
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.
|
||||
@@ -178,23 +174,18 @@ bool setupGtkBase(QLibrary &lib_gtk) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
f_gtk_init_check gtk_init_check = nullptr;
|
||||
f_gtk_settings_get_default gtk_settings_get_default = 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_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;
|
||||
f_gtk_selection_data_free gtk_selection_data_free = 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;
|
||||
@@ -232,32 +223,16 @@ 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_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_atom_intern gdk_atom_intern = 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_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha = nullptr;
|
||||
f_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels = nullptr;
|
||||
f_gdk_pixbuf_get_width gdk_pixbuf_get_width = nullptr;
|
||||
f_gdk_pixbuf_get_height gdk_pixbuf_get_height = nullptr;
|
||||
f_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride = nullptr;
|
||||
f_g_object_get g_object_get = 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;
|
||||
f_g_log_set_handler g_log_set_handler = nullptr;
|
||||
f_g_log_default_handler g_log_default_handler = nullptr;
|
||||
@@ -265,6 +240,10 @@ f_g_log_default_handler g_log_default_handler = nullptr;
|
||||
|
||||
void start() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (!UseGtkIntegration()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_LOG(("Loading libraries"));
|
||||
|
||||
bool gtkLoaded = false;
|
||||
@@ -279,23 +258,7 @@ void start() {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@@ -47,42 +47,15 @@ extern f_gtk_init_check gtk_init_check;
|
||||
typedef GtkSettings* (*f_gtk_settings_get_default)(void);
|
||||
extern f_gtk_settings_get_default gtk_settings_get_default;
|
||||
|
||||
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;
|
||||
|
||||
@@ -98,6 +71,18 @@ 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 GtkSelectionData* (*f_gtk_clipboard_wait_for_contents)(GtkClipboard *clipboard, GdkAtom target);
|
||||
extern f_gtk_clipboard_wait_for_contents gtk_clipboard_wait_for_contents;
|
||||
|
||||
typedef GdkPixbuf* (*f_gtk_clipboard_wait_for_image)(GtkClipboard *clipboard);
|
||||
extern f_gtk_clipboard_wait_for_image gtk_clipboard_wait_for_image;
|
||||
|
||||
typedef gboolean (*f_gtk_selection_data_targets_include_image)(const GtkSelectionData *selection_data, gboolean writable);
|
||||
extern f_gtk_selection_data_targets_include_image gtk_selection_data_targets_include_image;
|
||||
|
||||
typedef void (*f_gtk_selection_data_free)(GtkSelectionData *data);
|
||||
extern f_gtk_selection_data_free gtk_selection_data_free;
|
||||
|
||||
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;
|
||||
|
||||
@@ -190,16 +175,6 @@ 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;
|
||||
|
||||
@@ -273,84 +248,36 @@ inline gulong g_signal_connect_swapped_helper(gpointer instance, const gchar *de
|
||||
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 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 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_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 gboolean (*f_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_has_alpha gdk_pixbuf_get_has_alpha;
|
||||
|
||||
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 guchar* (*f_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_pixels gdk_pixbuf_get_pixels;
|
||||
|
||||
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 int (*f_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_width gdk_pixbuf_get_width;
|
||||
|
||||
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 int (*f_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_height gdk_pixbuf_get_height;
|
||||
|
||||
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 int (*f_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
|
||||
extern f_gdk_pixbuf_get_rowstride gdk_pixbuf_get_rowstride;
|
||||
|
||||
typedef void (*f_g_object_get)(gpointer object, const gchar *first_property_name, ...) G_GNUC_NULL_TERMINATED;
|
||||
extern f_g_object_get g_object_get;
|
||||
|
||||
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;
|
||||
|
||||
|
@@ -443,6 +443,11 @@ void ForceDisabled(QAction *action, bool disabled) {
|
||||
|
||||
MainWindow::MainWindow(not_null<Window::Controller*> controller)
|
||||
: Window::MainWindow(controller) {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (Libs::gtk_clipboard_get != nullptr) {
|
||||
_gtkClipboard = Libs::gtk_clipboard_get(Libs::gdk_atom_intern("CLIPBOARD", true));
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
}
|
||||
|
||||
void MainWindow::initHook() {
|
||||
|
@@ -18,6 +18,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include <dbusmenuexporter.h>
|
||||
#endif
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
typedef struct _GtkClipboard GtkClipboard;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
|
||||
namespace Platform {
|
||||
|
||||
class MainWindow : public Window::MainWindow {
|
||||
@@ -70,6 +75,12 @@ public slots:
|
||||
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
GtkClipboard *gtkClipboard() {
|
||||
return _gtkClipboard;
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
protected:
|
||||
void initHook() override;
|
||||
void unreadCounterChangedHook() override;
|
||||
@@ -133,6 +144,10 @@ private:
|
||||
void attachToSNITrayIcon();
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
GtkClipboard *_gtkClipboard = nullptr;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
};
|
||||
|
||||
} // namespace Platform
|
||||
|
@@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
#include "base/platform/base_platform_info.h"
|
||||
#include "platform/linux/specific_linux.h"
|
||||
#include "history/history.h"
|
||||
#include "lang/lang_keys.h"
|
||||
@@ -70,7 +71,7 @@ void GetSupported() {
|
||||
}
|
||||
Checked = true;
|
||||
|
||||
if (Global::NativeNotifications()) {
|
||||
if (Global::NativeNotifications() && !Platform::IsWayland()) {
|
||||
ComputeSupported(true);
|
||||
} else {
|
||||
ComputeSupported();
|
||||
@@ -474,7 +475,8 @@ std::unique_ptr<Window::Notifications::Manager> Create(
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
GetSupported();
|
||||
|
||||
if (Global::NativeNotifications() && Supported()) {
|
||||
if ((Global::NativeNotifications() && Supported())
|
||||
|| Platform::IsWayland()) {
|
||||
return std::make_unique<Manager>(system);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
@@ -488,6 +490,10 @@ Manager::Private::Private(not_null<Manager*> manager, Type type)
|
||||
, _manager(manager) {
|
||||
qDBusRegisterMetaType<NotificationData::ImageData>();
|
||||
|
||||
if (!Supported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto serverInformation = GetServerInformation();
|
||||
const auto capabilities = GetCapabilities();
|
||||
|
||||
@@ -520,6 +526,8 @@ void Manager::Private::showNotification(
|
||||
const QString &msg,
|
||||
bool hideNameAndPhoto,
|
||||
bool hideReplyButton) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto notification = std::make_shared<NotificationData>(
|
||||
_manager,
|
||||
title,
|
||||
@@ -558,6 +566,8 @@ void Manager::Private::showNotification(
|
||||
}
|
||||
|
||||
void Manager::Private::clearAll() {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto temp = base::take(_notifications);
|
||||
for_const (auto ¬ifications, temp) {
|
||||
for_const (auto notification, notifications) {
|
||||
@@ -567,6 +577,8 @@ void Manager::Private::clearAll() {
|
||||
}
|
||||
|
||||
void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto i = _notifications.find(history->peer->id);
|
||||
if (i != _notifications.cend()) {
|
||||
auto temp = base::take(i.value());
|
||||
@@ -579,6 +591,8 @@ void Manager::Private::clearFromHistory(not_null<History*> history) {
|
||||
}
|
||||
|
||||
void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) {
|
||||
if (!Supported()) return;
|
||||
|
||||
auto i = _notifications.find(peerId);
|
||||
if (i != _notifications.cend()) {
|
||||
i.value().remove(msgId);
|
||||
|
@@ -55,6 +55,8 @@ constexpr auto kXDGDesktopPortalService = "org.freedesktop.portal.Desktop"_cs;
|
||||
constexpr auto kXDGDesktopPortalObjectPath = "/org/freedesktop/portal/desktop"_cs;
|
||||
constexpr auto kPropertiesInterface = "org.freedesktop.DBus.Properties"_cs;
|
||||
|
||||
QStringList PlatformThemes;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_DBUS_INTEGRATION
|
||||
void PortalAutostart(bool autostart, bool silent = false) {
|
||||
QVariantMap options;
|
||||
@@ -295,14 +297,22 @@ bool IsStaticBinary() {
|
||||
#endif // !DESKTOP_APP_USE_PACKAGED
|
||||
}
|
||||
|
||||
bool UseGtkIntegration() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
static const auto Result = !qEnvironmentVariableIsSet(
|
||||
"TDESKTOP_DISABLE_GTK_INTEGRATION");
|
||||
|
||||
return Result;
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsGtkIntegrationForced() {
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
static const auto Result = [&] {
|
||||
const auto platformThemes = QString::fromUtf8(qgetenv("QT_QPA_PLATFORMTHEME"))
|
||||
.split(':', QString::SkipEmptyParts);
|
||||
|
||||
return platformThemes.contains(qstr("gtk3"), Qt::CaseInsensitive)
|
||||
|| platformThemes.contains(qstr("gtk2"), Qt::CaseInsensitive);
|
||||
return PlatformThemes.contains(qstr("gtk3"), Qt::CaseInsensitive)
|
||||
|| PlatformThemes.contains(qstr("gtk2"), Qt::CaseInsensitive);
|
||||
}();
|
||||
|
||||
return Result;
|
||||
@@ -346,7 +356,6 @@ bool UseXDGDesktopPortal() {
|
||||
|
||||
return (
|
||||
DesktopEnvironment::IsKDE()
|
||||
|| InSnap()
|
||||
|| envVar
|
||||
) && portalPresent;
|
||||
}();
|
||||
@@ -510,6 +519,43 @@ QString GetIconName() {
|
||||
return Result;
|
||||
}
|
||||
|
||||
QImage GetImageFromClipboard() {
|
||||
QImage data;
|
||||
|
||||
#ifndef TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
if (!App::wnd()->gtkClipboard()) {
|
||||
return data;
|
||||
}
|
||||
|
||||
auto gsel = Libs::gtk_clipboard_wait_for_contents(
|
||||
App::wnd()->gtkClipboard(),
|
||||
Libs::gdk_atom_intern("TARGETS", true));
|
||||
|
||||
if (gsel) {
|
||||
if (Libs::gtk_selection_data_targets_include_image(gsel, false)) {
|
||||
auto img = Libs::gtk_clipboard_wait_for_image(App::wnd()->gtkClipboard());
|
||||
|
||||
if (img) {
|
||||
data = QImage(
|
||||
Libs::gdk_pixbuf_get_pixels(img),
|
||||
Libs::gdk_pixbuf_get_width(img),
|
||||
Libs::gdk_pixbuf_get_height(img),
|
||||
Libs::gdk_pixbuf_get_rowstride(img),
|
||||
Libs::gdk_pixbuf_get_has_alpha(img)
|
||||
? QImage::Format_RGBA8888
|
||||
: QImage::Format_RGB888).copy();
|
||||
|
||||
Libs::g_object_unref(img);
|
||||
}
|
||||
}
|
||||
|
||||
Libs::gtk_selection_data_free(gsel);
|
||||
}
|
||||
#endif // !TDESKTOP_DISABLE_GTK_INTEGRATION
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
std::optional<crl::time> LastUserInputTime() {
|
||||
// TODO: a fallback pure-X11 implementation, this one covers only major DEs on X11 and Wayland
|
||||
// an example: https://stackoverflow.com/q/9049087
|
||||
@@ -697,6 +743,9 @@ int psFixPrevious() {
|
||||
namespace Platform {
|
||||
|
||||
void start() {
|
||||
PlatformThemes = QString::fromUtf8(qgetenv("QT_QPA_PLATFORMTHEME"))
|
||||
.split(':', QString::SkipEmptyParts);
|
||||
|
||||
LOG(("Launcher filename: %1").arg(GetLauncherFilename()));
|
||||
|
||||
#ifdef TDESKTOP_USE_FONTCONFIG_FALLBACK
|
||||
@@ -706,6 +755,16 @@ void start() {
|
||||
qputenv("PULSE_PROP_application.name", AppName.utf8());
|
||||
qputenv("PULSE_PROP_application.icon_name", GetIconName().toLatin1());
|
||||
|
||||
// if gtk integration and qgtk3/qgtk2 platformtheme (or qgtk2 style)
|
||||
// is used at the same time, the app will crash
|
||||
if (UseGtkIntegration()
|
||||
&& !IsStaticBinary()
|
||||
&& !qEnvironmentVariableIsSet(
|
||||
"TDESKTOP_I_KNOW_ABOUT_GTK_INCOMPATIBILITY")) {
|
||||
qunsetenv("QT_QPA_PLATFORMTHEME");
|
||||
qunsetenv("QT_STYLE_OVERRIDE");
|
||||
}
|
||||
|
||||
if(IsStaticBinary()
|
||||
|| InAppImage()
|
||||
|| InFlatpak()
|
||||
|
@@ -24,6 +24,7 @@ bool InFlatpak();
|
||||
bool InSnap();
|
||||
bool InAppImage();
|
||||
bool IsStaticBinary();
|
||||
bool UseGtkIntegration();
|
||||
bool IsGtkIntegrationForced();
|
||||
bool UseGtkFileDialog();
|
||||
bool IsQtPluginsBundled();
|
||||
@@ -34,10 +35,8 @@ bool CanOpenDirectoryWithPortal();
|
||||
|
||||
QString ProcessNameByPID(const QString &pid);
|
||||
QString RealExecutablePath(int argc, char *argv[]);
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString AppRuntimeDirectory();
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
QString GetLauncherBasename();
|
||||
QString GetLauncherFilename();
|
||||
|
@@ -16,10 +16,6 @@ class LocationPoint;
|
||||
|
||||
namespace Platform {
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
void RemoveQuarantine(const QString &path);
|
||||
|
||||
inline void FallbackFontConfigCheckBegin() {
|
||||
@@ -28,6 +24,10 @@ inline void FallbackFontConfigCheckBegin() {
|
||||
inline void FallbackFontConfigCheckEnd() {
|
||||
}
|
||||
|
||||
inline QImage GetImageFromClipboard() {
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
inline void start() {
|
||||
|
@@ -19,7 +19,9 @@ void DeInit();
|
||||
|
||||
// Platform dependent implementations.
|
||||
|
||||
#if defined Q_OS_MAC || defined Q_OS_LINUX
|
||||
#if defined Q_OS_WINRT || defined Q_OS_WIN
|
||||
#include "platform/win/audio_win.h"
|
||||
#else // Q_OS_WINRT || Q_OS_WIN
|
||||
namespace Platform {
|
||||
namespace Audio {
|
||||
|
||||
@@ -31,6 +33,4 @@ inline void DeInit() {
|
||||
|
||||
} // namespace Audio
|
||||
} // namespace Platform
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#include "platform/win/audio_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_WINRT || Q_OS_WIN
|
||||
|
@@ -46,8 +46,8 @@ bool Get(
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/file_utilities_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/file_utilities_linux.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/file_utilities_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
|
||||
|
@@ -23,8 +23,8 @@ namespace Platform {
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/launcher_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/launcher_linux.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/launcher_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WINRT || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WINRT || Q_OS_WIN
|
||||
|
@@ -19,8 +19,8 @@ class MainWindow;
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/main_window_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/main_window_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/main_window_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@@ -27,8 +27,8 @@ namespace Notifications {
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/notifications_manager_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/notifications_manager_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/notifications_manager_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@@ -28,6 +28,8 @@ enum class SystemSettingsType {
|
||||
|
||||
void SetWatchingMediaKeys(bool watching);
|
||||
void SetApplicationIcon(const QIcon &icon);
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
void RegisterCustomScheme(bool force = false);
|
||||
PermissionStatus GetPermissionStatus(PermissionType type);
|
||||
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback);
|
||||
@@ -41,6 +43,7 @@ bool OpenSystemSettings(SystemSettingsType type);
|
||||
|
||||
void IgnoreApplicationActivationRightNow();
|
||||
bool AutostartSupported();
|
||||
QImage GetImageFromClipboard();
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
@@ -52,8 +55,8 @@ void finish();
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
#include "platform/mac/specific_mac.h"
|
||||
#elif defined Q_OS_LINUX // Q_OS_MAC
|
||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||
#include "platform/linux/specific_linux.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_LINUX
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC || Q_OS_UNIX
|
||||
#include "platform/win/specific_win.h"
|
||||
#endif // Q_OS_MAC || Q_OS_LINUX || Q_OS_WIN
|
||||
#endif // Q_OS_MAC || Q_OS_UNIX || Q_OS_WIN
|
||||
|
@@ -26,7 +26,7 @@ void PreviewWindowFramePaint(QImage &preview, const style::palette &palette, QRe
|
||||
#include "platform/mac/window_title_mac.h"
|
||||
#elif defined Q_OS_WIN // Q_OS_MAC
|
||||
#include "platform/win/window_title_win.h"
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_LINUX // Q_OS_MAC || Q_OS_WIN
|
||||
#elif defined Q_OS_WINRT || defined Q_OS_UNIX // Q_OS_MAC || Q_OS_WIN
|
||||
|
||||
namespace Platform {
|
||||
|
||||
@@ -44,4 +44,4 @@ inline void PreviewWindowFramePaint(QImage &preview, const style::palette &palet
|
||||
|
||||
} // namespace Platform
|
||||
|
||||
#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_LINUX
|
||||
#endif // Q_OS_MAC || Q_OS_WIN || Q_OS_WINRT || Q_OS_UNIX
|
||||
|
@@ -19,10 +19,6 @@ namespace Platform {
|
||||
inline void SetWatchingMediaKeys(bool watching) {
|
||||
}
|
||||
|
||||
QString CurrentExecutablePath(int argc, char *argv[]);
|
||||
|
||||
QString SingleInstanceLocalServerName(const QString &hash);
|
||||
|
||||
inline void IgnoreApplicationActivationRightNow() {
|
||||
}
|
||||
|
||||
@@ -32,6 +28,10 @@ inline void FallbackFontConfigCheckBegin() {
|
||||
inline void FallbackFontConfigCheckEnd() {
|
||||
}
|
||||
|
||||
inline QImage GetImageFromClipboard() {
|
||||
return {};
|
||||
}
|
||||
|
||||
namespace ThirdParty {
|
||||
|
||||
void start();
|
||||
|
Reference in New Issue
Block a user