42 #define LIBSSH_STATIC 1 43 #include <libssh/libssh.h> 45 #include <X11/XKBlib.h> 46 #include <X11/extensions/XKBrules.h> 50 #define REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL 1 51 #define REMMINA_PLUGIN_NX_FEATURE_GTKSOCKET 1 86 gtk_socket_add_id( d->
sk, d->
w );
89 pthread_mutex_unlock( &d->
mu );
94 return G_SOURCE_REMOVE;
100 TRACE_CALL(__func__);
108 TRACE_CALL(__func__);
111 pthread_mutex_init( &d->
mu, NULL );
112 pthread_mutex_lock( &d->
mu );
115 pthread_mutex_lock( &d->mu );
117 pthread_cleanup_pop(0);
118 pthread_mutex_unlock( &d->mu );
119 pthread_mutex_destroy( &d->mu );
124 TRACE_CALL(__func__);
144 TRACE_CALL(__func__);
146 gboolean found = FALSE;
165 TRACE_CALL(__func__);
167 gboolean found = FALSE;
184 TRACE_CALL(__func__);
190 TRACE_CALL(__func__);
196 TRACE_CALL(__func__);
202 _(
"SSH credentials"), NULL,
205 _(
"Password for private SSH key"));
206 if (ret == GTK_RESPONSE_OK) {
215 TRACE_CALL(__func__);
223 TRACE_CALL(__func__);
229 TRACE_CALL(__func__);
232 gpdata->
display = XOpenDisplay(gdk_display_get_name(gdk_display_get_default()));
238 XSelectInput(gpdata->
display, XDefaultRootWindow(gpdata->
display), SubstructureNotifyMask);
245 TRACE_CALL(__func__);
252 unsigned long nitems, rest;
253 unsigned char *data = NULL;
258 gpdata = GET_PLUGIN_DATA(gp);
259 atom = XInternAtom(gpdata->display,
"WM_COMMAND", True);
264 ts.tv_nsec = 200000000;
267 pthread_testcancel();
268 while (!XPending(gpdata->display)) {
269 nanosleep(&ts, NULL);
272 XNextEvent(gpdata->display, &xev);
273 if (xev.type != CreateNotify)
275 w = xev.xcreatewindow.window;
276 if (XGetWindowProperty(gpdata->display, w, atom, 0, 255, False, AnyPropertyType, &type, &format, &nitems, &rest,
280 gpdata->window_id =
w;
288 XSetErrorHandler(gpdata->orig_handler);
289 XCloseDisplay(gpdata->display);
290 gpdata->display = NULL;
298 TRACE_CALL(__func__);
304 select(gpdata->
event_pipe[0] + 1, &
set, NULL, NULL, NULL);
312 TRACE_CALL(__func__);
316 const gchar *type, *app;
320 gboolean is_empty_list;
324 gboolean disablepasswordstoring;
332 remmina_plugin_nx_service->
file_get_int(remminafile,
"disableencryption", FALSE) ? 0 : 1);
352 s1 = g_strdup(remmina_plugin_nx_service->
file_get_string(remminafile,
"username"));
353 s2 = g_strdup(remmina_plugin_nx_service->
file_get_string(remminafile,
"password"));
358 gchar *s_username, *s_password;
360 disablepasswordstoring = remmina_plugin_nx_service->
file_get_int(remminafile,
"disablepasswordstoring", FALSE);
364 _(
"Enter NX authentication credentials"),
369 if (ret == GTK_RESPONSE_OK) {
375 remmina_plugin_nx_service->
file_set_string(remminafile,
"username", s_username);
376 remmina_plugin_nx_service->
file_set_string(remminafile,
"password", s_password);
397 if (!cs || g_strcmp0(cs,
"GNOME") == 0) {
401 if (g_strcmp0(cs,
"KDE") == 0) {
405 if (g_strcmp0(cs,
"Xfce") == 0) {
407 type =
"unix-application";
410 if (g_strcmp0(cs,
"Shadow") == 0) {
414 type =
"unix-application";
443 if (!is_empty_list) {
461 i = remmina_plugin_nx_service->
file_get_int(remminafile,
"quality", 0);
470 remmina_plugin_nx_service->
file_get_int(remminafile,
"disableclipboard", FALSE) ?
"none" :
"both");
472 switch (event_type) {
481 remmina_plugin_nx_service->
file_get_int(remminafile,
"resolution_width", 0),
482 remmina_plugin_nx_service->
file_get_int(remminafile,
"resolution_height", 0));
540 TRACE_CALL(__func__);
560 TRACE_CALL(__func__);
562 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
573 TRACE_CALL(__func__);
578 g_object_set_data_full(G_OBJECT(gp),
"plugin-data", gpdata, g_free);
580 gpdata->
socket = gtk_socket_new();
582 gtk_widget_show(gpdata->
socket);
585 gtk_container_add(GTK_CONTAINER(gp), gpdata->
socket);
588 g_print(
"Error creating pipes.\n");
592 flags = fcntl(gpdata->
event_pipe[0], F_GETFL, 0);
593 fcntl(gpdata->
event_pipe[0], F_SETFL, flags | O_NONBLOCK);
599 TRACE_CALL(__func__);
605 _(
"The protocol \"%s\" is unavailable because GtkSocket only works under X.Org."),
606 remmina_plugin_nx.
name);
615 gtk_widget_set_size_request(GTK_WIDGET(gp), width, height);
621 "Failed to initialize pthread. Falling back to non-thread mode…");
631 TRACE_CALL(__func__);
635 pthread_cancel(gpdata->
thread);
637 pthread_join(gpdata->
thread, NULL);
655 XCloseDisplay(gpdata->
display);
669 TRACE_CALL(__func__);
670 guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete };
674 keys, G_N_ELEMENTS(keys), GDK_KEY_PRESS | GDK_KEY_RELEASE);
679 TRACE_CALL(__func__);
685 TRACE_CALL(__func__);
686 switch (feature->
id) {
687 case REMMINA_PLUGIN_NX_FEATURE_TOOL_SENDCTRLALTDEL:
698 "0",
N_(
"Poor (fastest)"),
701 "9",
N_(
"Best (slowest)"),
758 N_(
"NX - NX Technology"),
761 "remmina-nx-symbolic",
762 "remmina-nx-symbolic",
776 G_MODULE_EXPORT gboolean
779 TRACE_CALL(__func__);
784 remmina_plugin_nx_service = service;
786 bindtextdomain(GETTEXT_PACKAGE, REMMINA_RUNTIME_LOCALEDIR);
787 bind_textdomain_codeset(GETTEXT_PACKAGE,
"UTF-8");
789 if ((dpy = XkbOpenDisplay(NULL, NULL, NULL, NULL, NULL, NULL)) != NULL) {
790 if (XkbRF_GetNamesProp(dpy, NULL, &vd)) {
static gboolean remmina_plugin_nx_monitor_create_notify(RemminaProtocolWidget *gp, const gchar *cmd)
gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, RemminaNXPassphraseCallback passphrase_func, gpointer userdata)
G_MODULE_EXPORT gboolean remmina_plugin_entry(RemminaPluginService *service)
void remmina_nx_session_set_log_callback(RemminaNXSession *nx, RemminaNXLogCallback log_callback)
void remmina_nx_session_set_localport(RemminaNXSession *nx, gint localport)
void(* debug)(const gchar *fmt,...)
void(* protocol_plugin_set_error)(RemminaProtocolWidget *gp, const gchar *fmt,...)
gboolean remmina_nx_session_attach(RemminaNXSession *nx)
gboolean remmina_nx_session_tunnel_open(RemminaNXSession *nx)
void(* protocol_plugin_init_save_cred)(RemminaProtocolWidget *gp)
gboolean remmina_nx_session_start(RemminaNXSession *nx)
typedefG_BEGIN_DECLS struct _RemminaFile RemminaFile
static void remmina_plugin_nx_on_plug_removed(GtkSocket *socket, RemminaProtocolWidget *gp)
void(* protocol_plugin_set_width)(RemminaProtocolWidget *gp, gint width)
static gboolean remmina_plugin_nx_try_window_id(Window window_id)
static void onMainThread_cleanup_handler(gpointer data)
gboolean remmina_nx_session_invoke_proxy(RemminaNXSession *nx, gint display, GChildWatchFunc exit_func, gpointer user_data)
static void remmina_plugin_nx_on_proxy_exit(GPid pid, gint status, gpointer data)
const gchar * remmina_nx_session_get_error(RemminaNXSession *nx)
void(* protocol_plugin_send_keys_signals)(GtkWidget *widget, const guint *keyvals, int length, GdkEventType action)
gint(* pref_get_sshtunnel_port)(void)
void(* protocol_plugin_signal_connection_closed)(RemminaProtocolWidget *gp)
static gboolean remmina_plugin_nx_start_create_notify(RemminaProtocolWidget *gp)
static void onMainThread_schedule_callback_and_wait(struct onMainThread_cb_data *d)
void remmina_nx_session_manager_start(RemminaProtocolWidget *gp)
void(* get_server_port)(const gchar *server, gint defaultport, gchar **host, gint *port)
gint(* file_get_int)(RemminaFile *remminafile, const gchar *setting, gint default_value)
RemminaNXSession * remmina_nx_session_new(void)
static const RemminaProtocolSetting remmina_plugin_nx_basic_settings[]
void(* protocol_plugin_signal_connection_opened)(RemminaProtocolWidget *gp)
static void remmina_plugin_nx_call_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
static const RemminaProtocolSetting remmina_plugin_nx_advanced_settings[]
static gboolean remmina_plugin_nx_open_connection(RemminaProtocolWidget *gp)
static gchar * remmina_kbtype
gboolean(* protocol_plugin_init_get_savepassword)(RemminaProtocolWidget *gp)
static RemminaProtocolPlugin remmina_plugin_nx
gboolean remmina_plugin_nx_ssh_auth_callback(gchar **passphrase, gpointer userdata)
void remmina_nx_session_free(RemminaNXSession *nx)
static gint remmina_plugin_nx_wait_signal(RemminaPluginNxData *gpdata)
gboolean(* register_plugin)(RemminaPlugin *plugin)
void remmina_nx_session_set_encryption(RemminaNXSession *nx, gint encryption)
static void remmina_plugin_nx_init(RemminaProtocolWidget *gp)
gboolean(* gtksocket_available)(void)
gboolean remmina_nx_session_list(RemminaNXSession *nx)
static gboolean remmina_plugin_nx_start_session(RemminaProtocolWidget *gp)
static const RemminaProtocolFeature remmina_plugin_nx_features[]
static gpointer quality_list[]
void remmina_nx_session_add_parameter(RemminaNXSession *nx, const gchar *name, const gchar *valuefmt,...)
gchar * remmina_nx_session_iter_get(RemminaNXSession *nx, GtkTreeIter *iter, gint column)
static gboolean remmina_plugin_nx_close_connection(RemminaProtocolWidget *gp)
gint(* protocol_plugin_init_auth)(RemminaProtocolWidget *gp, RemminaMessagePanelFlags pflags, const gchar *title, const gchar *default_username, const gchar *default_password, const gchar *default_domain, const gchar *password_prompt)
enum onMainThread_cb_data::@37 func
static void remmina_plugin_nx_on_plug_added(GtkSocket *socket, RemminaProtocolWidget *gp)
gint(* get_profile_remote_height)(RemminaProtocolWidget *gp)
RemminaFile *(* protocol_plugin_get_file)(RemminaProtocolWidget *gp)
static gboolean remmina_plugin_nx_query_feature(RemminaProtocolWidget *gp, const RemminaProtocolFeature *feature)
guint session_manager_start_handler
static gboolean remmina_plugin_nx_main(RemminaProtocolWidget *gp)
void(* file_unsave_passwords)(RemminaFile *remminafile)
gchar *(* protocol_plugin_init_get_username)(RemminaProtocolWidget *gp)
gint(* get_profile_remote_width)(RemminaProtocolWidget *gp)
gchar *(* protocol_plugin_init_get_password)(RemminaProtocolWidget *gp)
static gboolean onMainThread_cb(struct onMainThread_cb_data *d)
static void onMainThread_gtk_socket_add_id(GtkSocket *sk, Window w)
static int remmina_plugin_nx_dummy_handler(Display *dsp, XErrorEvent *err)
void(* protocol_plugin_register_hostkey)(RemminaProtocolWidget *gp, GtkWidget *widget)
gboolean remmina_nx_session_terminate(RemminaNXSession *nx)
RemminaProtocolWidget * gp
void(* file_set_string)(RemminaFile *remminafile, const gchar *setting, const gchar *value)
void(* protocol_plugin_set_height)(RemminaProtocolWidget *gp, gint height)
static pthread_mutex_t remmina_nx_init_mutex
gboolean remmina_nx_session_login(RemminaNXSession *nx, const gchar *username, const gchar *password)
static void remmina_plugin_nx_send_ctrlaltdel(RemminaProtocolWidget *gp)
int(* orig_handler)(Display *, XErrorEvent *)
RemminaPluginService * remmina_plugin_nx_service
gchar *(* protocol_plugin_start_direct_tunnel)(RemminaProtocolWidget *gp, gint default_port, gboolean port_plus)
gboolean remmina_nx_session_iter_first(RemminaNXSession *nx, GtkTreeIter *iter)
const gchar *(* file_get_string)(RemminaFile *remminafile, const gchar *setting)
static GArray * remmina_nx_window_id_array
N_("Unable to connect to VNC server")
gboolean remmina_nx_session_restore(RemminaNXSession *nx)
static void remmina_plugin_nx_remove_window_id(Window window_id)
static gpointer remmina_plugin_nx_main_thread(gpointer data)