diff options
author | Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de> | 2021-11-22 18:44:21 +0300 |
---|---|---|
committer | Daniel Teichmann <daniel.teichmann@das-netzwerkteam.de> | 2021-11-23 18:24:57 +0300 |
commit | 3c502e931aaffe1a2d49ad49ae8f4a4bba884ed5 (patch) | |
tree | 2c99bfe8052c5a56cb58ecb32d237ea4929a5c56 /plugins/x2go | |
parent | d814a0f9aeb004da5aa3166a8475249477e46dfb (diff) |
x2go_plugin.c: Refactor use of X2GoCustomUserData struct for dialogs.
Fixes non-session-chooser dialogs again.
Diffstat (limited to 'plugins/x2go')
-rw-r--r-- | plugins/x2go/x2go_plugin.c | 215 |
1 files changed, 149 insertions, 66 deletions
diff --git a/plugins/x2go/x2go_plugin.c b/plugins/x2go/x2go_plugin.c index fa11ec297..d6c4241ed 100644 --- a/plugins/x2go/x2go_plugin.c +++ b/plugins/x2go/x2go_plugin.c @@ -90,12 +90,6 @@ NULL) // ------------------- -#define SET_DIALOG_DATA(gp, ddata) \ - g_object_set_data_full(G_OBJECT(gp), "dialog-data", ddata, g_free); - -#define GET_DIALOG_DATA(gp) \ - (struct _DialogData*) g_object_get_data(G_OBJECT(gp), "dialog-data"); - #define REMMINA_PLUGIN_INFO(fmt, ...) \ rm_plugin_service->_remmina_info("[%s] " fmt, \ PLUGIN_NAME, ##__VA_ARGS__) @@ -157,10 +151,9 @@ typedef struct _RemminaPluginX2GoData { */ typedef struct _X2GoCustomUserData { RemminaProtocolWidget* gp; - gpointer user_data; + gpointer dialog_data; + gpointer connect_data; gpointer opt1; - gpointer opt2; - gpointer opt3; } X2GoCustomUserData; /** @@ -278,8 +271,9 @@ struct _DialogData }; /** - * @param gp getting DialogData via dialog-data saved in gp. - * See define GET_DIALOG_DATA + * @param custom_data X2GoCustomUserData structure with the following: \n + * gp -> gp (RemminaProtocolWidget*) \n + * dialog_data -> dialog data (struct _DialogData*) * @returns: FALSE. This source should be removed from main loop. * #G_SOURCE_CONTINUE and #G_SOURCE_REMOVE are more memorable * names for the return value. @@ -288,7 +282,7 @@ static gboolean rmplugin_x2go_open_dialog(X2GoCustomUserData *custom_data) { REMMINA_PLUGIN_DEBUG("Function entry."); - if (!custom_data || !custom_data->gp || !custom_data->user_data ) { + if (!custom_data || !custom_data->gp || !custom_data->dialog_data) { REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( _("Internal error: %s"), _("Parameter 'custom_data' is not initialized!") @@ -297,7 +291,8 @@ static gboolean rmplugin_x2go_open_dialog(X2GoCustomUserData *custom_data) return G_SOURCE_REMOVE; } - struct _DialogData* ddata = GET_DIALOG_DATA(custom_data->gp); + RemminaProtocolWidget *gp = (RemminaProtocolWidget*) custom_data->gp; + struct _DialogData *ddata = (struct _DialogData*) custom_data->dialog_data; if (ddata) { // Can't check type, flags or buttons @@ -320,9 +315,9 @@ static gboolean rmplugin_x2go_open_dialog(X2GoCustomUserData *custom_data) GCallback dialog_factory_func = G_CALLBACK(ddata->dialog_factory_func); gpointer dialog_factory_data = ddata->dialog_factory_data; - // Calling dialog_factory_func(gp, dialog_factory_data); - widget_gtk_dialog = ((GtkWidget* (*)(RemminaProtocolWidget*, gpointer)) - dialog_factory_func)(custom_data->gp, dialog_factory_data); + // Calling dialog_factory_func(custom_data, dialog_factory_data); + widget_gtk_dialog = ((GtkWidget* (*)(X2GoCustomUserData*, gpointer)) + dialog_factory_func)(custom_data, dialog_factory_data); } else { widget_gtk_dialog = gtk_message_dialog_new(ddata->parent, ddata->flags, @@ -352,7 +347,7 @@ static gboolean rmplugin_x2go_open_dialog(X2GoCustomUserData *custom_data) gtk_widget_show_all(widget_gtk_dialog); // Delete ddata object and reference 'dialog-data' in gp. - g_object_set_data(G_OBJECT(custom_data->gp), "dialog-data", NULL); + g_object_set_data(G_OBJECT(gp), "dialog-data", NULL); return G_SOURCE_REMOVE; } @@ -407,6 +402,10 @@ static GtkWidget* rmplugin_x2go_find_child(GtkWidget* parent, const gchar* name) * the user double clicks a treeview row. It is also emitted when a non-editable * row is selected and one of the keys: Space, Shift+Space, Return or Enter is * pressed. + * + * @param custom_data X2GoCustomUserData structure with the following: \n + * gp -> gp (RemminaProtocolWidget*) \n + * opt1 -> dialog widget (GtkWidget*) */ static gboolean rmplugin_x2go_session_chooser_row_activated(GtkTreeView *treeview, GtkTreePath *path, @@ -415,12 +414,20 @@ static gboolean rmplugin_x2go_session_chooser_row_activated(GtkTreeView *treevie { REMMINA_PLUGIN_DEBUG("Function entry."); - // Safety first. - g_assert(custom_data); - g_assert(custom_data->gp); - g_assert(custom_data->user_data); + if (!custom_data || !custom_data->gp || !custom_data->opt1) { + REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( + _("Internal error: %s"), + _("Parameter 'custom_data' is not initialized!") + )); + + return G_SOURCE_REMOVE; + } + + RemminaProtocolWidget* gp = (RemminaProtocolWidget*) custom_data->gp; + // dialog_data (unused) + // connect_data (unused) + GtkWidget* dialog = GTK_WIDGET(custom_data->opt1); - GtkWidget* dialog = GTK_WIDGET(custom_data->user_data); gchar *session_id; GtkTreeIter iter; GtkTreeModel *model = gtk_tree_view_get_model(treeview); @@ -432,12 +439,12 @@ static gboolean rmplugin_x2go_session_chooser_row_activated(GtkTreeView *treevie // Silent bail out. if (!session_id || strlen(session_id) <= 0) return G_SOURCE_REMOVE; - SET_RESUME_SESSION(custom_data->gp, session_id); + SET_RESUME_SESSION(gp, session_id); // Unstucking main process. Telling it that a session has been selected. // We use a trick here. As long as there is something other than 0 // stored, a session is selected. So we use the gpointer as a gboolean. - SET_SESSION_SELECTED(custom_data->gp, (gpointer) TRUE); + SET_SESSION_SELECTED(gp, (gpointer) TRUE); gtk_widget_hide(GTK_WIDGET(dialog)); gtk_widget_destroy(GTK_WIDGET(dialog)); } @@ -446,28 +453,41 @@ static gboolean rmplugin_x2go_session_chooser_row_activated(GtkTreeView *treevie } /** - * @brief Builds a dialog which contains all found X2Go-Sessions. of the remote server - * And gives the user the option to choose between an existing session or - * to create a new one. + * @brief Builds a dialog which contains all found X2Go-Sessions of the remote server. + * The dialog gives the user the option to choose between resuming or terminating + * an existing session or to create a new one. * - * @param gp Gets used to get the struct _Dialogdata. + * @param custom_data X2GoCustomUserData structure with the following: \n + * gp -> gp (RemminaProtocolWidget*) \n + * dialog_data -> dialog data (struct _DialogData*) \n + * connect_data -> connection data (struct _ConnectionData*) * @param sessions_list The GList* Should contain all found X2Go-Sessions. * Sessions are string arrays of properties. * The type of the GList is gchar**. * * @returns GtkWidget* custom dialog. */ -static GtkWidget* rmplugin_x2go_choose_session_dialog_factory(RemminaProtocolWidget* gp, +static GtkWidget* rmplugin_x2go_choose_session_dialog_factory(X2GoCustomUserData *custom_data, GList *sessions_list) { REMMINA_PLUGIN_DEBUG("Function entry."); - struct _DialogData* ddata = GET_DIALOG_DATA(gp); + if (!custom_data || !custom_data->gp || + !custom_data->dialog_data || !custom_data->connect_data) { + REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( + _("Internal error: %s"), + _("Parameter 'custom_data' is not initialized!") + )); + + return NULL; + } + + struct _DialogData* ddata = (struct _DialogData*) custom_data->dialog_data; if (!ddata || !sessions_list || !ddata->title) { REMMINA_PLUGIN_CRITICAL("%s", _("Couldn't retrieve valid `DialogData` or " "`sessions_list`! Aborting…")); - return FALSE; + return NULL; } GtkWidget *widget_gtk_dialog = NULL; @@ -595,13 +615,18 @@ static GtkWidget* rmplugin_x2go_choose_session_dialog_factory(RemminaProtocolWid } } - X2GoCustomUserData *user_data = g_new0(X2GoCustomUserData, 1); - user_data->gp = gp; - user_data->user_data = widget_gtk_dialog; + /* Prepare X2GoCustomUserData *custom_data + * gp -> gp (RemminaProtocolWidget*) + * dialog_data -> dialog data (struct _DialogData*) + * connect_data -> connection data (struct _ConnectionData*) + * opt1 -> dialog widget (GtkWidget*) + */ + // everything else is already initialized. + custom_data->opt1 = widget_gtk_dialog; g_signal_connect(tree_view, "row-activated", G_CALLBACK(rmplugin_x2go_session_chooser_row_activated), - user_data); + custom_data); return widget_gtk_dialog; } @@ -894,9 +919,10 @@ struct _ConnectionData { * @brief Terminates a specific X2Go session using pyhoca-cli. * * @param custom_data X2GoCustomUserData structure with the following: \n - * * gp = RemminaProtocolWidget* \n - * * user_data = struct _ConnectionData* \n - * * opt1 = gchar* session_id \n + * gp -> gp (RemminaProtocolWidget*) \n + * dialog_data -> dialog data (struct _DialogData*) \n + * connect_data -> connection data (struct _ConnectionData*) \n + * opt1 -> session id (gchar*) * * @return G_SOURCE_REMOVE (FALSE), #G_SOURCE_CONTINUE and #G_SOURCE_REMOVE are more * memorable names for the return value. See GLib docs. \n @@ -906,8 +932,8 @@ static gboolean rmplugin_x2go_pyhoca_terminate_session(X2GoCustomUserData *custo { REMMINA_PLUGIN_DEBUG("Function entry."); - if (!custom_data || !custom_data->gp || !custom_data->user_data || - !custom_data->opt1) { + if (!custom_data || !custom_data->gp || + !custom_data->dialog_data || !custom_data->connect_data || !custom_data->opt1) { REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( _("Internal error: %s"), _("Parameter 'custom_data' is not fully initialized!") @@ -916,13 +942,13 @@ static gboolean rmplugin_x2go_pyhoca_terminate_session(X2GoCustomUserData *custo return G_SOURCE_REMOVE; } - RemminaProtocolWidget *gp = custom_data->gp; - RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(gp); - - struct _ConnectionData *connect_data = (struct _ConnectionData*) custom_data->user_data; - + // Extract data passed by X2GoCustomUserData *custom_data. + RemminaPluginX2GoData *gpdata = GET_PLUGIN_DATA(custom_data->gp); + //struct _DialogData *ddata = (struct _DialogData*) custom_data->dialog_data; + struct _ConnectionData *connect_data = (struct _ConnectionData*) custom_data->connect_data; gchar *session_id = (gchar*) custom_data->opt1; + /* Check connect_data. */ gchar *host = NULL; gchar *username = NULL; gchar *password = NULL; @@ -947,6 +973,7 @@ static gboolean rmplugin_x2go_pyhoca_terminate_session(X2GoCustomUserData *custo password = connect_data->password; } + /* Check session_id. */ if (!session_id || strlen(session_id) <= 0) { REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( _("Internal error: %s"), @@ -1021,7 +1048,10 @@ static gboolean rmplugin_x2go_pyhoca_terminate_session(X2GoCustomUserData *custo /** * @brief Gets executed on dialog's 'response' signal * - * @param gp Needed by SET_RESUME_SESSION to set the session id of the selected session. + * @param custom_data X2GoCustomUserData*: \n + * gp -> gp (RemminaProtocolWidget*) \n + * dialog_data -> dialog data (struct _DialogData*) \n + * connect_data -> connection data (struct _ConnectionData*) * @param response_id See GTK 'response' signal. * @param self The dialog itself. * @@ -1035,7 +1065,7 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo { REMMINA_PLUGIN_DEBUG("Function entry."); - if (!custom_data || !custom_data->gp || !custom_data->user_data ) { + if (!custom_data || !custom_data->gp || !custom_data->dialog_data) { REMMINA_PLUGIN_CRITICAL("%s", g_strdup_printf( _("Internal error: %s"), _("Parameter 'custom_data' is not initialized!") @@ -1043,6 +1073,7 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo return G_SOURCE_REMOVE; } + RemminaProtocolWidget *gp = (RemminaProtocolWidget*) custom_data->gp; if (response_id == SESSION_CHOOSER_RESPONSE_CHOOSE) { gchar* session_id = rmplugin_x2go_session_chooser_get_property( @@ -1055,9 +1086,9 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo "%s", _("Couldn't get session ID from session chooser dialog.") ); - SET_RESUME_SESSION(custom_data->gp, NULL); + SET_RESUME_SESSION(gp, NULL); } else { - SET_RESUME_SESSION(custom_data->gp, session_id); + SET_RESUME_SESSION(gp, session_id); REMMINA_PLUGIN_MESSAGE("%s", g_strdup_printf( _("Resuming session: '%s'"), @@ -1067,7 +1098,7 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo } else if (response_id == SESSION_CHOOSER_RESPONSE_NEW) { REMMINA_PLUGIN_DEBUG("User explicitly wishes a new session. " "Creating a new session then."); - SET_RESUME_SESSION(custom_data->gp, NULL); + SET_RESUME_SESSION(gp, NULL); } else if (response_id == SESSION_CHOOSER_RESPONSE_TERMINATE) { gchar* session_id = rmplugin_x2go_session_chooser_get_property( GTK_WIDGET(self), @@ -1079,9 +1110,9 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo "%s", _("Couldn't get session ID from session chooser dialog.") ); - SET_RESUME_SESSION(custom_data->gp, NULL); + SET_RESUME_SESSION(gp, NULL); } else { - SET_RESUME_SESSION(custom_data->gp, session_id); + SET_RESUME_SESSION(gp, session_id); REMMINA_PLUGIN_MESSAGE("%s", g_strdup_printf( _("Terminating session: '%s'"), @@ -1123,8 +1154,16 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo gtk_widget_set_sensitive(resume_button, FALSE); } - // Actually start pyhoca-cli process with --terminate $session_id. + /* Prepare X2GoCustomUserData *custom_data + * gp -> gp (RemminaProtocolWidget*) + * dialog_data -> dialog data (struct _DialogData*) + * connect_data -> connection data (struct _ConnectionData*) + * opt1 -> session id (gchar*) + */ + // everything else is already initialized. custom_data->opt1 = session_id; + + // Actually start pyhoca-cli process with --terminate $session_id. g_thread_new("terminate-session-thread", (GThreadFunc) rmplugin_x2go_pyhoca_terminate_session, custom_data); @@ -1134,13 +1173,13 @@ static gboolean rmplugin_x2go_session_chooser_callback(X2GoCustomUserData* custo } else { REMMINA_PLUGIN_DEBUG("User clicked dialog away. " "Creating a new session then."); - SET_RESUME_SESSION(custom_data->gp, NULL); + SET_RESUME_SESSION(gp, NULL); } // Unstucking main process. Telling it that a session has been selected. // We use a trick here. As long as there is something other // than 0 stored, a session is selected. So we use the gpointer as a gboolean. - SET_SESSION_SELECTED(custom_data->gp, (gpointer) TRUE); + SET_SESSION_SELECTED(gp, (gpointer) TRUE); gtk_widget_destroy(GTK_WIDGET(self)); @@ -1335,7 +1374,6 @@ static void rmplugin_x2go_pyhoca_cli_exited(GPid pid, "This connection will now be closed.")); struct _DialogData *ddata = g_new0(struct _DialogData, 1); - SET_DIALOG_DATA(gp, ddata); ddata->parent = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(gp))); ddata->flags = GTK_DIALOG_MODAL; ddata->type = GTK_MESSAGE_ERROR; @@ -1350,7 +1388,20 @@ static void rmplugin_x2go_pyhoca_cli_exited(GPid pid, // We don't need a custom dialog either. ddata->dialog_factory_func = NULL; ddata->dialog_factory_data = NULL; - IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, gp); + + /* Prepare X2GoCustomUserData *custom_data + * gp -> gp (RemminaProtocolWidget*) + * dialog_data -> dialog data (struct _DialogData*) + */ + X2GoCustomUserData *custom_data = g_new0(X2GoCustomUserData, 1); + g_assert(custom_data && "custom_data could not be initialized."); + + custom_data->gp = gp; + custom_data->dialog_data = ddata; + custom_data->connect_data = NULL; + custom_data->opt1 = NULL; + + IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, custom_data); // 1 Second. Give `Dialog` chance to open. usleep(1000 * 1000); @@ -1779,8 +1830,8 @@ static GList* rmplugin_x2go_parse_pyhoca_sessions(RemminaProtocolWidget* gp, } /** - * @brief Asks the user, with the help of a dialog, whether he or she would like - * to continue an already existing session. + * @brief Asks the user, with the help of a dialog, to continue an already existing + * session, terminate or create a new one. * * @param error Is set if there is something to tell the user. \n * Not necessarily an *error* message. @@ -1819,21 +1870,41 @@ static gchar* rmplugin_x2go_ask_session(RemminaProtocolWidget *gp, GError **erro // Prep new DialogData struct. struct _DialogData *ddata = g_new0(struct _DialogData, 1); - SET_DIALOG_DATA(gp, ddata); ddata->parent = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(gp))); ddata->flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT; //ddata->type = GTK_MESSAGE_QUESTION; //ddata->buttons = GTK_BUTTONS_OK; // Doesn't get used in our custom factory. ddata->title = _("Choose a session to resume:"); ddata->message = ""; + + // gboolean factory(X2GoCustomUserData*, gpointer) + // X2GoCustomUserData*: + // gp -> gp (RemminaProtocolWidget*) + // dialog_data -> dialog data (struct _DialogData*) + // connect_data -> connection data (struct _ConnectionData*) + // gpointer: dialog_factory_data ddata->callbackfunc = G_CALLBACK(rmplugin_x2go_session_chooser_callback); - ddata->dialog_factory_func = G_CALLBACK(rmplugin_x2go_choose_session_dialog_factory); + + // gboolean factory(X2GoCustomUserData*, gpointer) + // X2GoCustomUserData*: + // gp -> gp (RemminaProtocolWidget*) + // dialog_data -> dialog data (struct _DialogData*) + // connect_data -> connection data (struct _ConnectionData*) + // gpointer: dialog_factory_data ddata->dialog_factory_data = sessions_list; + ddata->dialog_factory_func = G_CALLBACK(rmplugin_x2go_choose_session_dialog_factory); + + /* Prepare X2GoCustomUserData *custom_data + * gp -> gp (RemminaProtocolWidget*) + * dialog_data -> dialog data (struct _DialogData*) + */ + X2GoCustomUserData *custom_data = g_new0(X2GoCustomUserData, 1); + g_assert(custom_data && "custom_data could not be initialized."); - X2GoCustomUserData *custom_data = g_new(X2GoCustomUserData, 1); - g_assert(custom_data != NULL); custom_data->gp = gp; - custom_data->user_data = (gpointer) connect_data; + custom_data->dialog_data = ddata; + custom_data->connect_data = connect_data; + custom_data->opt1 = NULL; // Open dialog here. Dialog rmplugin_x2go_session_chooser_callback (callbackfunc) // should set SET_RESUME_SESSION. @@ -2097,7 +2168,6 @@ static gboolean rmplugin_x2go_exec_x2go(gchar *host, "starting an X2Go session…"); struct _DialogData* ddata = g_new0(struct _DialogData, 1); - SET_DIALOG_DATA(gp, ddata); ddata->parent = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(gp))); ddata->flags = GTK_DIALOG_MODAL; ddata->type = GTK_MESSAGE_ERROR; @@ -2111,7 +2181,20 @@ static gboolean rmplugin_x2go_exec_x2go(gchar *host, // We don't need a custom dialog either. ddata->dialog_factory_func = NULL; ddata->dialog_factory_data = NULL; - IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, gp); + + /* Prepare X2GoCustomUserData *custom_data + * gp -> gp (RemminaProtocolWidget*) + * dialog_data -> dialog data (struct _DialogData*) + */ + X2GoCustomUserData *custom_data = g_new0(X2GoCustomUserData, 1); + g_assert(custom_data && "custom_data could not be initialized."); + + custom_data->gp = gp; + custom_data->dialog_data = ddata; + custom_data->connect_data = NULL; + custom_data->opt1 = NULL; + + IDLE_ADD((GSourceFunc) rmplugin_x2go_open_dialog, custom_data); g_strlcpy(errmsg, error_title, 512); |