Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/Remmina/Remmina.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/ui/CMakeLists.txt1
-rw-r--r--data/ui/remmina_xinput_env_dialog.glade84
-rw-r--r--src/rcw.c25
-rw-r--r--src/remmina_main.c47
-rw-r--r--src/remmina_pref.c6
-rw-r--r--src/remmina_pref.h1
6 files changed, 148 insertions, 16 deletions
diff --git a/data/ui/CMakeLists.txt b/data/ui/CMakeLists.txt
index 416bb254c..0e599d7a0 100644
--- a/data/ui/CMakeLists.txt
+++ b/data/ui/CMakeLists.txt
@@ -42,3 +42,4 @@ install(FILES remmina_string_list.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_mpc.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_snap_info_dialog.glade DESTINATION "${REMMINA_UIDIR}")
install(FILES remmina_unlock.glade DESTINATION "${REMMINA_UIDIR}")
+install(FILES remmina_xinput_env_dialog.glade DESTINATION "${REMMINA_UIDIR}")
diff --git a/data/ui/remmina_xinput_env_dialog.glade b/data/ui/remmina_xinput_env_dialog.glade
new file mode 100644
index 000000000..0fa74c6a1
--- /dev/null
+++ b/data/ui/remmina_xinput_env_dialog.glade
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.6"/>
+ <object class="GtkDialog" id="xinputwarndlg">
+ <property name="can_focus">False</property>
+ <property name="resizable">False</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="margin_left">5</property>
+ <property name="margin_right">5</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">15</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label">gtk-ok</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin_top">9</property>
+ <property name="label" translatable="yes">Remmina detected that your environment variable GDK_CORE_DEVICE_EVENTS is set.
+This could make remmina freeze when grabbing the keyboard, and touch events will not work too.
+Please unset GDK_CORE_DEVICE_EVENTS environment variable.</property>
+ <property name="wrap">True</property>
+ <property name="ellipsize">start</property>
+ <property name="max_width_chars">50</property>
+ <property name="lines">6</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="suppress">
+ <property name="label" translatable="yes">Suppress this message for 20 days</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="1">button1</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/src/rcw.c b/src/rcw.c
index 58e4c5472..636036da7 100644
--- a/src/rcw.c
+++ b/src/rcw.c
@@ -142,7 +142,6 @@ struct _RemminaConnectionWindowPriv {
gboolean ss_maximized;
gboolean kbcaptured;
- gboolean dont_ungrab_on_next_focus_out_event;
gboolean mouse_pointer_entered;
gboolean hostkey_activated;
gboolean hostkey_used;
@@ -516,15 +515,16 @@ static void rcw_keyboard_grab(RemminaConnectionWindow *cnnwin)
* The bugfix will be released with GTK 3.24.
* Also pease note that the newer gdk_seat_grab() is still calling gdk_device_grab().
*
- * dont_ungrab_on_next_focus_out_event: Xorg when grabbing keyboard
- * generates an extra focus-out and focus-in event
- * https://stackoverflow.com/questions/15270420/why-xgrabkey-generates-extra-focus-out-and-focus-in-events
- * with mode field set to XCB_NOTIFY_MODE_GRAB
- * Some windows managers can detect this evend via the mode==XCB_NOTIFY_MODE_GRAB and suppress it.
- * Some WM don't. Under GTK we can't check the mode field, so we need a workaround to block
- * the spurious focus-out event we receive, setting dont_ungrab_on_next_focus_out_event to true.
+ * Warning: gdk_seat_grab() will call XGrabKeyboard() or XIGrabDevice()
+ * which in turn will generate a core X input event FocusOut and FocusIn
+ * but not Xinput2 events.
+ * In some cases, GTK is unable to neutralize FocusIn and FocusOut core
+ * events (ie: i3wm+Plasma with GDK_CORE_DEVICE_EVENTS=1 because detail=NotifyNonlinear
+ * instead of detail=NotifyAncestor/detail=NotifyInferior)
+ * Receiving a FocusOut event for Remmina at this time will cause an infinite loop.
+ * Therefore is important for GTK to use Xinput2 insetead of core X events
+ * by unsetting GDK_CORE_DEVICE_EVENTS
*/
- cnnwin->priv->dont_ungrab_on_next_focus_out_event = TRUE;
#if GTK_CHECK_VERSION(3, 24, 0)
ggs = gdk_seat_grab(seat, gtk_widget_get_window(GTK_WIDGET(cnnwin)),
GDK_SEAT_CAPABILITY_KEYBOARD, FALSE, NULL, NULL, NULL, NULL);
@@ -2392,7 +2392,6 @@ static void rcw_focus_in(RemminaConnectionWindow *cnnwin)
TRACE_CALL(__func__);
RemminaConnectionObject *cnnobj;
- cnnwin->priv->dont_ungrab_on_next_focus_out_event = FALSE;
if (!(cnnobj = rcw_get_visible_cnnobj(cnnwin))) return;
if (cnnobj && cnnobj->connected && remmina_file_get_int(cnnobj->remmina_file, "keyboard_grab", FALSE))
@@ -2404,10 +2403,8 @@ static void rcw_focus_out(RemminaConnectionWindow *cnnwin)
TRACE_CALL(__func__);
RemminaConnectionObject *cnnobj;
- if (!cnnwin->priv->dont_ungrab_on_next_focus_out_event)
- rcw_keyboard_ungrab(cnnwin);
+ rcw_keyboard_ungrab(cnnwin);
- cnnwin->priv->dont_ungrab_on_next_focus_out_event = FALSE;
cnnwin->priv->hostkey_activated = FALSE;
if (!(cnnobj = rcw_get_visible_cnnobj(cnnwin))) return;
@@ -2455,7 +2452,6 @@ static gboolean rcw_on_enter(GtkWidget *widget, GdkEventCrossing *event, gpointe
return FALSE;
cnnwin = (RemminaConnectionWindow *)widget;
- cnnwin->priv->dont_ungrab_on_next_focus_out_event = FALSE;
if (!(cnnobj = rcw_get_visible_cnnobj(cnnwin))) return FALSE;
@@ -2487,7 +2483,6 @@ static gboolean rcw_on_leave(GtkWidget *widget, GdkEventCrossing *event, gpointe
if (!REMMINA_IS_CONNECTION_WINDOW(widget))
return FALSE;
cnnwin = (RemminaConnectionWindow *)widget;
- cnnwin->priv->dont_ungrab_on_next_focus_out_event = FALSE;
#if DEBUG_KB_GRABBING
printf("DEBUG_KB_GRABBING: leave detail=");
diff --git a/src/remmina_main.c b/src/remmina_main.c
index aa43ea2a9..b3654fea3 100644
--- a/src/remmina_main.c
+++ b/src/remmina_main.c
@@ -244,6 +244,51 @@ static void remmina_main_clear_selection_data(void)
remminamain->priv->selected_name = NULL;
}
+static void remmina_main_check_env()
+{
+ GtkBuilder *dlgbuilder = NULL;
+ GtkWidget *dlg;
+ GtkWindow *parent;
+ GtkWidget* dsa;
+ int result;
+ gint64 nowsec;
+ static gboolean shown_once = FALSE;
+ #define SUPPRESS_DAYS 20
+
+ if (shown_once)
+ return;
+ else
+ shown_once = TRUE;
+
+ static char envvar[] = "GDK_CORE_DEVICE_EVENTS";
+ if (g_getenv(envvar)) {
+ /* It seens that GTK4 no longer makes use of X core events, so all this stuff could be removed in GTK4 */
+ g_print("WARNING: Remmina can freeze during keyboard grab or miss some touch events because %s environment variable is set. Please unset it.\n", envvar);
+ nowsec = g_get_real_time() / 1000000;
+ if (nowsec > remmina_pref.suppress_xinput_welcome_message_time_limit && !kioskmode) {
+ dlgbuilder = remmina_public_gtk_builder_new_from_file("remmina_xinput_env_dialog.glade");
+ dsa = GTK_WIDGET(gtk_builder_get_object(dlgbuilder, "suppress"));
+ if (dlgbuilder) {
+ parent = remmina_main_get_window();
+ dlg = GTK_WIDGET(gtk_builder_get_object(dlgbuilder, "xinputwarndlg"));
+ if (parent)
+ gtk_window_set_transient_for(GTK_WINDOW(dlg), parent);
+ gtk_builder_connect_signals(dlgbuilder, NULL);
+ result = gtk_dialog_run(GTK_DIALOG(dlg));
+ if (result == 1) {
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dsa)))
+ remmina_pref.suppress_xinput_welcome_message_time_limit = (g_get_real_time() / 1000000) + SUPPRESS_DAYS * 60 * 60 * 24;
+ else
+ remmina_pref.suppress_xinput_welcome_message_time_limit = 0;
+ remmina_pref_save();
+ }
+ gtk_widget_destroy(dlg);
+ g_object_unref(dlgbuilder);
+ }
+ }
+ }
+}
+
#ifdef SNAP_BUILD
static void remmina_main_show_snap_welcome()
@@ -1284,7 +1329,7 @@ void remmina_main_on_show(GtkWidget *w, gpointer user_data)
#ifdef SNAP_BUILD
remmina_main_show_snap_welcome();
#endif
-
+ remmina_main_check_env();
}
/* RemminaMain instance */
diff --git a/src/remmina_pref.c b/src/remmina_pref.c
index 5d0bea612..ff275993f 100644
--- a/src/remmina_pref.c
+++ b/src/remmina_pref.c
@@ -314,6 +314,11 @@ void remmina_pref_init(void)
else
remmina_pref.prevent_snap_welcome_message = FALSE;
+ if (g_key_file_has_key(gkeyfile, "remmina_pref", "suppress_xinput_welcome_message_time_limit", NULL))
+ remmina_pref.suppress_xinput_welcome_message_time_limit = g_key_file_get_uint64(gkeyfile, "remmina_pref", "suppress_xinput_welcome_message_time_limit", NULL);
+ else
+ remmina_pref.suppress_xinput_welcome_message_time_limit = FALSE;
+
if (g_key_file_has_key(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL))
remmina_pref.last_quickconnect_protocol = g_key_file_get_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", NULL);
else
@@ -739,6 +744,7 @@ gboolean remmina_pref_save(void)
g_key_file_set_integer(gkeyfile, "remmina_pref", "floating_toolbar_placement", remmina_pref.floating_toolbar_placement);
g_key_file_set_integer(gkeyfile, "remmina_pref", "toolbar_placement", remmina_pref.toolbar_placement);
g_key_file_set_boolean(gkeyfile, "remmina_pref", "prevent_snap_welcome_message", remmina_pref.prevent_snap_welcome_message);
+ g_key_file_set_uint64(gkeyfile, "remmina_pref", "suppress_xinput_welcome_message_time_limit", remmina_pref.suppress_xinput_welcome_message_time_limit);
g_key_file_set_string(gkeyfile, "remmina_pref", "last_quickconnect_protocol", remmina_pref.last_quickconnect_protocol);
g_key_file_set_boolean(gkeyfile, "remmina_pref", "fullscreen_on_auto", remmina_pref.fullscreen_on_auto);
g_key_file_set_boolean(gkeyfile, "remmina_pref", "always_show_tab", remmina_pref.always_show_tab);
diff --git a/src/remmina_pref.h b/src/remmina_pref.h
index 0b7c93248..4348fefca 100644
--- a/src/remmina_pref.h
+++ b/src/remmina_pref.h
@@ -186,6 +186,7 @@ typedef struct _RemminaPref {
gint floating_toolbar_placement;
gint toolbar_placement;
gboolean prevent_snap_welcome_message;
+ guint64 suppress_xinput_welcome_message_time_limit;
gchar * last_quickconnect_protocol;
/* Crypto */