39 #include <glib/gi18n.h>
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
53 #ifdef GDK_WINDOWING_X11
56 #include <X11/Xutil.h>
57 #include <X11/Xatom.h>
58 #elif defined(GDK_WINDOWING_WAYLAND)
59 #include <gdk/gdkwayland.h>
70 gchar *buf, *ptr1, *ptr2;
76 combo = gtk_combo_box_text_new_with_entry();
79 if (text && text[0] !=
'\0') {
83 while (ptr1 && *ptr1 !=
'\0') {
84 ptr2 = strchr(ptr1, CHAR_DELIMITOR);
89 gtk_combo_box_text_prepend_text(GTK_COMBO_BOX_TEXT(combo), ptr1);
90 if (!found && g_strcmp0(ptr1, def) == 0) {
91 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
95 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ptr1);
96 if (!found && g_strcmp0(ptr1, def) == 0) {
97 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
109 if (!found && def && def[0] !=
'\0') {
110 gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(combo))), def);
119 TRACE_CALL(__func__);
122 GtkCellRenderer *text_renderer;
124 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
125 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
127 text_renderer = gtk_cell_renderer_text_new();
128 gtk_cell_layout_pack_end(GTK_CELL_LAYOUT(combo), text_renderer, TRUE);
129 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), text_renderer,
"text", 1);
138 TRACE_CALL(__func__);
142 gchar *buf, *ptr1, *ptr2;
144 store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
145 gtk_list_store_clear(store);
150 gtk_list_store_append(store, &iter);
151 gtk_list_store_set(store, &iter, 0,
"", 1, empty_choice, -1);
152 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
156 if (text == NULL || text[0] ==
'\0')
159 buf = g_strdup(text);
161 while (ptr1 && *ptr1 !=
'\0') {
162 ptr2 = strchr(ptr1, CHAR_DELIMITOR);
166 gtk_list_store_append(store, &iter);
167 gtk_list_store_set(store, &iter, 0, ptr1, 1, ptr1, -1);
169 if (i == 0 || g_strcmp0(ptr1, def) == 0) {
170 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
183 TRACE_CALL(__func__);
186 GtkCellRenderer *renderer;
189 store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
191 store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
193 combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
194 gtk_widget_set_hexpand(combo, TRUE);
197 renderer = gtk_cell_renderer_pixbuf_new();
198 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, FALSE);
199 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
"icon-name", 2);
201 renderer = gtk_cell_renderer_text_new();
202 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), renderer, TRUE);
203 gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(combo), renderer,
"text", 1);
205 g_object_set(G_OBJECT(renderer),
"xpad", 5, NULL);
213 TRACE_CALL(__func__);
220 store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo)));
222 for (i = 0; key_value_list[i]; i += (use_icon ? 3 : 2)) {
223 gtk_list_store_append(store, &iter);
230 key_value_list[i + 1] && ((
char*)key_value_list[i + 1])[0] ?
231 g_dgettext(domain, key_value_list[i + 1]) :
"", -1);
233 gtk_list_store_set(store, &iter, 2, key_value_list[i + 2], -1);
235 if (i == 0 || g_strcmp0(key_value_list[i], def) == 0) {
236 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i / (use_icon ? 3 : 2));
245 TRACE_CALL(__func__);
247 g_snprintf(buf,
sizeof(buf),
"%i", def);
253 TRACE_CALL(__func__);
257 widget = gtk_label_new(NULL);
258 gtk_widget_show(widget);
259 gtk_widget_set_halign(GTK_WIDGET(widget), GTK_ALIGN_START);
260 gtk_widget_set_valign(GTK_WIDGET(widget), GTK_ALIGN_CENTER);
261 str = g_markup_printf_escaped(
"<b>%s</b>", group);
262 gtk_label_set_markup(GTK_LABEL(widget), str);
264 gtk_grid_attach(GTK_GRID(grid), widget, 0, row, 1, 2);
266 widget = gtk_label_new(NULL);
267 gtk_widget_show(widget);
268 gtk_grid_attach(GTK_GRID(grid), widget, 0, row + 1, 1, 1);
274 TRACE_CALL(__func__);
279 if (GTK_IS_COMBO_BOX_TEXT(combo)) {
280 return gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
283 if (!gtk_combo_box_get_active_iter(combo, &iter))
286 model = gtk_combo_box_get_model(combo);
287 gtk_tree_model_get(model, &iter, 0, &s, -1);
292 #if !GTK_CHECK_VERSION(3, 22, 0)
295 TRACE_CALL(__func__);
298 GtkAllocation allocation;
300 widget = GTK_WIDGET(user_data);
301 if (gtk_widget_get_window(widget) == NULL) {
307 gdk_window_get_origin(gtk_widget_get_window(widget), &tx, &ty);
308 gtk_widget_get_allocation(widget, &allocation);
316 if (gtk_widget_get_has_window(widget) ||
317 g_strcmp0(gtk_widget_get_name(widget),
"GtkToggleToolButton") == 0) {
323 *y = ty + allocation.height - 1;
331 TRACE_CALL(__func__);
332 if (!path1 || path1[0] ==
'\0')
333 return g_strdup(path2);
334 if (path1[strlen(path1) - 1] ==
'/')
335 return g_strdup_printf(
"%s%s", path1, path2);
336 return g_strdup_printf(
"%s/%s", path1, path2);
342 struct sockaddr_un addr;
345 if (strlen(unixsock) + 1 >
sizeof(addr.sun_path)) {
347 g_debug(_(
"Address is too long for UNIX socket_path: %s"), unixsock);
351 memset(&addr, 0,
sizeof addr);
352 addr.sun_family = AF_UNIX;
353 strcpy(addr.sun_path, unixsock);
355 if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
357 g_debug(_(
"Creating UNIX socket failed: %s"), g_strerror(errno));
361 if (connect(fd, (
struct sockaddr *)&addr,
sizeof addr) < 0) {
363 g_debug(_(
"Connecting to UNIX socket failed: %s"), g_strerror(errno));
373 TRACE_CALL(__func__);
374 gchar *str, *ptr, *ptr2;
376 str = g_strdup(server);
380 ptr = strchr(str,
'[');
383 ptr2 = strchr(ptr,
']');
387 defaultport = atoi(ptr2 + 1);
390 *host = g_strdup(ptr);
394 g_debug (
"(%s) - host: %s", __func__, *host);
395 g_debug (
"(%s) - port: %d", __func__, *port);
400 ptr = strchr(str,
':');
402 ptr2 = strchr(ptr + 1,
':');
405 defaultport = atoi(ptr);
418 g_debug (
"(%s) - host: %s", __func__, *host);
419 g_debug (
"(%s) - port: %d", __func__, *port);
424 TRACE_CALL(__func__);
426 const gchar *nul_terminated_server = NULL;
427 if (server != NULL) {
428 if(strstr(g_strdup(server),
"ID:") != NULL) {
429 g_debug (
"(%s) - Using remmina_public_get_server_port_old to parse the repeater ID", __func__);
434 GNetworkAddress *address;
437 nul_terminated_server = g_strdup (server);
438 g_debug (
"(%s) - Parsing server: %s, default port: %d", __func__, server, defaultport);
439 address = (GNetworkAddress*)g_network_address_parse ((
const gchar *)nul_terminated_server, defaultport, &err);
441 if (address == NULL) {
442 g_debug (
"(%s) - Error converting server string: %s, with error: %s", __func__, nul_terminated_server, err->message);
448 *host = g_strdup(g_network_address_get_hostname (address));
449 *port = g_network_address_get_port (address);
457 g_debug (
"(%s) - host: %s", __func__, *host);
458 g_debug (
"(%s) - port: %d", __func__, *port);
465 TRACE_CALL(__func__);
469 GError *error = NULL;
473 display = gdk_display_get_name(gdk_display_get_default());
475 g_snprintf(buf,
sizeof(buf),
"xauth list %s", display);
476 ret = g_spawn_command_line_sync(buf, &out, NULL, NULL, &error);
478 if ((ptr = g_strrstr(out,
"MIT-MAGIC-COOKIE-1")) == NULL) {
479 *msg = g_strdup_printf(
"xauth returns %s", out);
485 *msg = g_strndup(ptr, 32);
489 *msg = g_strdup(error->message);
496 TRACE_CALL(__func__);
500 struct sockaddr_un addr;
503 display = g_strdup(disp);
504 ptr = g_strrstr(display,
":");
508 if (display[0] ==
'\0' || strcmp(display,
"unix") == 0) {
510 sock = socket(AF_UNIX, SOCK_STREAM, 0);
512 memset(&addr, 0,
sizeof(addr));
513 addr.sun_family = AF_UNIX;
514 snprintf(addr.sun_path,
sizeof(addr.sun_path), X_UNIX_SOCKET, port);
515 if (connect(sock, (
struct sockaddr *)&addr,
sizeof(addr)) == -1) {
530 TRACE_CALL(__func__);
531 GdkKeymapKey *keys = NULL;
535 if (gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &length)) {
536 keycode = keys[0].keycode;
545 TRACE_CALL(__func__);
547 if (keycode > 0)
return FALSE;
548 #ifdef GDK_WINDOWING_X11
549 return gdk_x11_keymap_key_is_modifier(keymap, keycode);
558 TRACE_CALL(__func__);
560 gchar *ui_path = g_strconcat(REMMINA_RUNTIME_UIDIR, G_DIR_SEPARATOR_S, filename, NULL);
561 GtkBuilder *builder = gtk_builder_new();
562 gtk_builder_add_from_file(builder, ui_path, &err);
564 g_print(
"Error adding build from file. Error: %s", err->message);
574 TRACE_CALL(__func__);
576 GtkBuilder *builder = gtk_builder_new();
577 gtk_builder_add_from_resource (builder, resource, &err);
580 g_print(
"Error adding build from resource. Error: %s", err->message);
590 TRACE_CALL(__func__);
591 g_object_ref(widget);
592 gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(widget)), widget);
593 gtk_container_add(container, widget);
594 g_object_unref(widget);
600 TRACE_CALL(__func__);
610 for (i = 0; new_str[i] !=
'\0'; i++) {
611 if (new_str[i] ==
'x') {
619 if (new_str[i] <
'0' || new_str[i] >
'9') {
630 if (width == 0 || height == 0)
634 *error = g_strdup(_(
"Please enter format 'widthxheight'."));
640 const gchar *notification_title,
const gchar *notification_message)
642 TRACE_CALL(__func__);
644 g_autoptr(GNotification) n = NULL;
645 gint priority = G_NOTIFICATION_PRIORITY_NORMAL;
647 n = g_notification_new(notification_title);
648 g_notification_set_body(n, notification_message);
649 if (g_strcmp0 (notification_id,
"remmina-security-trust-all-id") == 0) {
650 g_debug (
"remmina_public_send_notification: We got a remmina-security-trust-all-id notification");
651 priority = G_NOTIFICATION_PRIORITY_HIGH;
655 g_notification_set_default_action_and_target (n,
"app.preferences",
"i", 5);
656 g_notification_add_button_with_target (n, _(
"Change security settings"),
"app.preferences",
"i", 5);
658 #if GLIB_CHECK_VERSION(2, 42, 0)
659 g_notification_set_priority(n, priority);
661 g_application_send_notification(g_application_get_default(), notification_id, n);
667 TRACE_CALL(__func__);
670 g_return_val_if_fail(
string != NULL, NULL);
671 g_return_val_if_fail(search != NULL, NULL);
673 if (replacement == NULL)
676 arr = g_strsplit(
string, search, -1);
677 if (arr != NULL && arr[0] != NULL)
678 str = g_strjoinv(replacement, arr);
680 str = g_strdup(
string);
690 TRACE_CALL(__func__);
692 string = g_strdup(new_string);
701 if (resolution_string == NULL || resolution_string[0] == 0)
703 if (sscanf(resolution_string,
"%dx%d", &lw, &lh) != 2)
714 guint rtmajor, rtminor, rtmicro;
715 rtmajor = gtk_get_major_version();
716 if (rtmajor > major) {
718 }
else if (rtmajor == major) {
719 rtminor = gtk_get_minor_version();
720 if (rtminor > minor) {
722 }
else if (rtminor == minor) {
723 rtmicro = gtk_get_micro_version();
724 if (rtmicro >= micro) {
gboolean remmina_public_resolution_validation_func(const gchar *new_str, gchar **error)
gboolean remmina_public_get_xauth_cookie(const gchar *display, gchar **msg)
gboolean remmina_public_get_modifier_for_keycode(GdkKeymap *keymap, guint16 keycode)
GtkBuilder * remmina_public_gtk_builder_new_from_file(gchar *filename)
GtkWidget * remmina_public_create_combo_text_d(const gchar *text, const gchar *def, const gchar *empty_choice)
GtkBuilder * remmina_public_gtk_builder_new_from_resource(gchar *resource)
gint remmina_public_open_unix_sock(const char *unixsock)
Return a file descriptor handle for a unix socket.
gint remmina_public_open_xdisplay(const gchar *disp)
GtkWidget * remmina_public_create_combo_map(const gpointer *key_value_list, const gchar *def, gboolean use_icon, const gchar *domain)
gchar * remmina_public_combine_path(const gchar *path1, const gchar *path2)
void remmina_public_send_notification(const gchar *notification_id, const gchar *notification_title, const gchar *notification_message)
gchar * remmina_public_str_replace_in_place(gchar *string, const gchar *search, const gchar *replacement)
void remmina_public_popup_position(GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user_data)
guint16 remmina_public_get_keycode_for_keyval(GdkKeymap *keymap, guint keyval)
GtkWidget * remmina_public_create_combo_entry(const gchar *text, const gchar *def, gboolean descending)
void remmina_public_load_combo_text_d(GtkWidget *combo, const gchar *text, const gchar *def, const gchar *empty_choice)
int remmina_public_split_resolution_string(const char *resolution_string, int *w, int *h)
GtkWidget * remmina_public_create_combo(gboolean use_icon)
void remmina_public_gtk_widget_reparent(GtkWidget *widget, GtkContainer *container)
GtkWidget * remmina_public_create_combo_mapint(const gpointer *key_value_list, gint def, gboolean use_icon, const gchar *domain)
gboolean remmina_gtk_check_version(guint major, guint minor, guint micro)
void remmina_public_get_server_port_old(const gchar *server, gint defaultport, gchar **host, gint *port)
void remmina_public_get_server_port(const gchar *server, gint defaultport, gchar **host, gint *port)
gchar * remmina_public_str_replace(const gchar *string, const gchar *search, const gchar *replacement)
gchar * remmina_public_combo_get_active_text(GtkComboBox *combo)
void remmina_public_create_group(GtkGrid *grid, const gchar *group, gint row, gint rows, gint cols)