diff --git a/sflphone-client-gnome/src/callable_obj.c b/sflphone-client-gnome/src/callable_obj.c index e165857433d975f76096b6e3a6acac22e59f2cfe..66b0503b48122386870de5357c91fea6b31ddede 100644 --- a/sflphone-client-gnome/src/callable_obj.c +++ b/sflphone-client-gnome/src/callable_obj.c @@ -423,3 +423,14 @@ time_t convert_gchar_to_timestamp (gchar *timestamp) { return (time_t) atoi (timestamp); } + + gchar* +get_peer_information (callable_obj_t *c) { + + gchar *res; + + if (g_strcasecmp (c->_peer_name,"") == 0) + return g_strdup (c->_peer_number); + else + return g_strdup (c->_peer_name); +} diff --git a/sflphone-client-gnome/src/callable_obj.h b/sflphone-client-gnome/src/callable_obj.h index a3d4f252ee92e868339b7ad1c0785f9b2decf712..acab0ed3ea55e59ac858a16bb433c75e931f4ba7 100644 --- a/sflphone-client-gnome/src/callable_obj.h +++ b/sflphone-client-gnome/src/callable_obj.h @@ -224,4 +224,6 @@ time_t convert_gchar_to_timestamp (gchar*); gchar* call_get_audio_codec (callable_obj_t *obj); +gchar* get_peer_information (callable_obj_t *c); + #endif diff --git a/sflphone-client-gnome/src/dbus/dbus.c b/sflphone-client-gnome/src/dbus/dbus.c index 2fbeb378d187613a1cff59fd2ae814889787e07a..5acd8c35f5014d24818dd4cbd844f34cd88ae92e 100644 --- a/sflphone-client-gnome/src/dbus/dbus.c +++ b/sflphone-client-gnome/src/dbus/dbus.c @@ -127,7 +127,13 @@ incoming_message_cb(DBusGProxy *proxy UNUSED, const gchar* callID UNUSED, // Get the call information. Does this call exist? callable_obj_t * c = calllist_get (current_calls, callID); + + /* Make the instant messaging main window pops */ + im_widget_display (&c); + + /* Display le message */ im_widget_add_message (c, msg); + if (c) { notify_incoming_message (callID, msg); } else { diff --git a/sflphone-client-gnome/src/imwindow.c b/sflphone-client-gnome/src/imwindow.c index eb20ca626b4ca9c49b6f5706964270164af666d9..b805b5751c6995e07cdd5affc9b3a5efba40201d 100644 --- a/sflphone-client-gnome/src/imwindow.c +++ b/sflphone-client-gnome/src/imwindow.c @@ -39,7 +39,7 @@ /** Local variables */ GtkWidget *im_window = NULL; -GtkWidget *im_vbox = NULL; +GtkWidget *im_notebook = NULL; static gboolean window_configure_cb (GtkWidget *win, GdkEventConfigure *event) { int pos_x, pos_y; @@ -57,15 +57,15 @@ static gboolean window_configure_cb (GtkWidget *win, GdkEventConfigure *event) { /** * Minimize the main window. */ -static gboolean + static gboolean on_delete(GtkWidget * widget UNUSED, gpointer data UNUSED) { - gtk_widget_hide(GTK_WIDGET(im_window_get())); - // gtk_widget_destroy (GTK_WIDGET(im_window_get())); + /* Only hide the main window that contains all the instant messaging instances */ + gtk_widget_hide (GTK_WIDGET(im_window_get())); return TRUE; } -static void + static void im_window_init() { const char *window_title = "SFLphone VoIP Client - Instant Messaging Module"; @@ -94,14 +94,18 @@ im_window_init() gtk_widget_set_name(im_window, "imwindow"); g_signal_connect (G_OBJECT (im_window), "delete-event", - G_CALLBACK (on_delete), NULL); + G_CALLBACK (on_delete), NULL); g_signal_connect_object (G_OBJECT (im_window), "configure-event", - G_CALLBACK (window_configure_cb), NULL, 0); + G_CALLBACK (window_configure_cb), NULL, 0); + + GtkWidget *im_vbox = gtk_vbox_new (FALSE /*homogeneous*/, 0 /*spacing*/); + im_notebook = gtk_notebook_new (); - im_vbox = gtk_vbox_new (FALSE /*homogeneous*/, 0 /*spacing*/); gtk_container_add (GTK_CONTAINER (im_window), im_vbox); + gtk_box_pack_start (GTK_BOX (im_vbox), im_notebook, TRUE, TRUE, 0); + gtk_widget_show (im_notebook); /* make sure that everything is visible */ gtk_widget_show_all (im_window); @@ -110,7 +114,7 @@ im_window_init() gtk_window_move (GTK_WINDOW (im_window), position_x, position_y); } -GtkWidget * + GtkWidget * im_window_get() { if (im_window == NULL) @@ -119,16 +123,62 @@ im_window_get() } void -im_window_add (GtkWidget *widget) +im_window_show (){ + gtk_widget_show (im_window_get ()); +} + + void +im_window_add (GtkWidget *widget, gchar *label) { if (im_window_get()) { - gtk_box_pack_start (GTK_BOX (im_vbox), widget, TRUE /*expand*/, - TRUE /*fill*/, 0 /*padding*/); + /* Add the new tab to the notebook */ + im_window_add_tab (widget, label); + + /* Switch to the newly opened tab */ + guint index = gtk_notebook_page_num (GTK_NOTEBOOK (im_notebook), widget); + gtk_notebook_set_current_page (GTK_NOTEBOOK (im_notebook), 2); + g_print ("index %i - current %i\n", index, gtk_notebook_get_current_page (GTK_NOTEBOOK (im_notebook))); + + /* Show it all */ gtk_widget_show_all (im_window); } + else + error ("Could not create the main instant messaging window"); } -void + static void +close_tab_cb (GtkButton *button, gpointer userdata) +{ + + /* We want here to close the current tab */ + guint index = gtk_notebook_page_num (GTK_NOTEBOOK (im_notebook), GTK_WIDGET (userdata)); + g_print ("removing index %i\n", index); + gtk_notebook_remove_page (GTK_NOTEBOOK (im_notebook), index); + +} + + void +im_window_add_tab (GtkWidget *widget, gchar *label) +{ + /* A container to include the tab label and the close button */ + GtkWidget *tab_Container = gtk_hbox_new (FALSE, 3); + GtkWidget *tab_Label = gtk_label_new (label); + GtkWidget *tab_CloseButton = gtk_button_new (); + + gtk_button_set_relief (GTK_BUTTON(tab_CloseButton), GTK_RELIEF_NONE); + gtk_box_pack_start (GTK_BOX (tab_Container), tab_Label, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (tab_Container), tab_CloseButton, FALSE, FALSE, 0); + gtk_container_add(GTK_CONTAINER (tab_CloseButton), gtk_image_new_from_stock (GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU)); + g_signal_connect (tab_CloseButton, "clicked", G_CALLBACK (close_tab_cb), widget); + + gtk_widget_show_all (tab_Container); + gtk_notebook_append_page (GTK_NOTEBOOK (im_notebook), widget, tab_Container); + +} + + + + void im_window_remove(GtkWidget *widget) { // TODO(jonas) remove widget from the window diff --git a/sflphone-client-gnome/src/imwindow.h b/sflphone-client-gnome/src/imwindow.h index 61128a415f78732318a14c0737620290b006d299..22d24e5007208b2c33f2b8db1fb19cb6e58f8f07 100644 --- a/sflphone-client-gnome/src/imwindow.h +++ b/sflphone-client-gnome/src/imwindow.h @@ -49,11 +49,16 @@ GtkWidget *im_window_get(); /** * Add IM widget to the IM window */ -void im_window_add(GtkWidget *widget); +void im_window_add(GtkWidget *widget, gchar *label); /** * Remove IM widget from the IM window */ void im_window_remove(GtkWidget *widget); +void im_window_show (); + +void im_window_add_tab (GtkWidget *widget, gchar *label); + + #endif diff --git a/sflphone-client-gnome/src/uimanager.c b/sflphone-client-gnome/src/uimanager.c index 602f25a333e49b8cd0efc25251c1bbffba91feba..faa3dda240908bfcec54bd24cda938767e54c598 100644 --- a/sflphone-client-gnome/src/uimanager.c +++ b/sflphone-client-gnome/src/uimanager.c @@ -509,20 +509,12 @@ call_hold(void* foo UNUSED) call_im (void* foo UNUSED) { callable_obj_t * selectedCall = calltab_get_selected_call(current_calls); - static IMWidget *im = NULL; - if (selectedCall) - { - if (selectedCall->_im_widget == NULL) { - printf("Call IM with call %s\n", selectedCall->_callID); - im = im_widget_new(); - im_window_add (im); - im->call = selectedCall; - selectedCall->_im_widget = im; - - /* Update the informations about the call in the chat window */ - im_widget_add_call_header (selectedCall); - } + if (selectedCall) { + im_widget_display (&selectedCall); + } + else { + warn ("Sorry. Instant messaging is not allowed outside a call\n"); } } diff --git a/sflphone-client-gnome/src/widget/imwidget.c b/sflphone-client-gnome/src/widget/imwidget.c index 0396a1ce91f361391e5d5557b93e149b21310195..b3d994d5aa15f603b67815434e8c08e17495cbf5 100644 --- a/sflphone-client-gnome/src/widget/imwidget.c +++ b/sflphone-client-gnome/src/widget/imwidget.c @@ -33,46 +33,57 @@ #define WEBKIT_DIR "file://" DATA_DIR "/webkit/" -static IMWidget *_this; - void im_widget_add_message (callable_obj_t *call, const gchar *message) { /* use the widget for this specific call, if exists */ - IMWidget *im = IM_WIDGET (call->_im_widget); // IM_WIDGET(widget); + if (!call){ + error ("The call passed as a parameter does not seem to be valid"); + } + else { - if (im) { + IMWidget *im = IM_WIDGET (call->_im_widget); - /* Prepare and execute the Javascript code */ - gchar *script = g_strdup_printf("add_message('%s', '%s', '%s', '%s');", message, call->_peer_name, call->_peer_number, call->_peer_info); - webkit_web_view_execute_script (WEBKIT_WEB_VIEW(_this->web_view), script); + if (im) { - /* Cleanup */ - g_free(script); - } + /* Update the informations about the call in the chat window */ + im_widget_add_call_header (call); - else { + /* Prepare and execute the Javascript code */ + gchar *script = g_strdup_printf("add_message('%s', '%s', '%s', '%s');", message, call->_peer_name, call->_peer_number, call->_peer_info); + webkit_web_view_execute_script (WEBKIT_WEB_VIEW(im->web_view), script); - im = im_widget_new (); - im_window_add (im); - im->call = call; - call->_im_widget = im; - - /* Prepare and execute the Javascript code */ - gchar *script = g_strdup_printf("add_message('%s', '%s', '%s', '%s');", message, call->_peer_name, call->_peer_number, call->_peer_info); - webkit_web_view_execute_script (WEBKIT_WEB_VIEW(_this->web_view), script); + /* Cleanup */ + g_free(script); - /* Cleanup */ - g_free(script); + } + else { + + /* If the chat window is not opened when we receive an incoming message, create the im widget first, + then call the javascript to display the message */ + + im = im_widget_new (); + im_window_add (im); + im->call = call; + call->_im_widget = im; + + /* Prepare and execute the Javascript code */ + gchar *script = g_strdup_printf("add_message('%s', '%s', '%s', '%s');", message, call->_peer_name, call->_peer_number, call->_peer_info); + webkit_web_view_execute_script (WEBKIT_WEB_VIEW(im->web_view), script); + + /* Cleanup */ + g_free(script); + } } } void im_widget_add_call_header (callable_obj_t *call) { + IMWidget *im = IM_WIDGET (call->_im_widget); gchar *script = g_strdup_printf("add_call_info_header('%s', '%s', '%s');", call->_peer_name, call->_peer_number, call->_peer_info); - webkit_web_view_execute_script (WEBKIT_WEB_VIEW(_this->web_view), script); + webkit_web_view_execute_script (WEBKIT_WEB_VIEW(im->web_view), script); /* Cleanup */ g_free(script); @@ -105,8 +116,9 @@ on_Textview_changed (GtkWidget *widget, GdkEventKey *event, gpointer user_data) GtkTextIter start, end; /* Get all the text in the buffer */ - GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (_this->textarea)); - + IMWidget *im = user_data; + GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (im->textarea)); + if (event->type == GDK_KEY_PRESS){ switch (event->keyval) @@ -119,10 +131,10 @@ on_Textview_changed (GtkWidget *widget, GdkEventKey *event, gpointer user_data) gchar *message = gtk_text_buffer_get_text (buffer, &start, &end, FALSE); /* Display our own message in the chat window */ - im_widget_add_message (_this->call, message); + im_widget_add_message (im->call, message); /* Send the message to the peer */ - dbus_send_text_message (_this->call->_callID, message); + dbus_send_text_message (im->call->_callID, message); /* Empty the buffer */ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &start, &end); @@ -165,17 +177,13 @@ im_widget_init (IMWidget *im) gtk_box_pack_start (GTK_BOX(im), webscrollwin, TRUE, TRUE, 5); gtk_box_pack_end (GTK_BOX(im), hbox, FALSE, FALSE, 2); g_signal_connect (im->web_view, "navigation-policy-decision-requested", G_CALLBACK (web_view_nav_requested_cb), NULL); - g_signal_connect(im->textarea, "key-press-event", G_CALLBACK (on_Textview_changed), NULL); + g_signal_connect(im->textarea, "key-press-event", G_CALLBACK (on_Textview_changed), im); g_signal_connect (G_OBJECT (webscrollwin), "destroy", G_CALLBACK (gtk_main_quit), NULL); im->web_frame = webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(im->web_view)); im->js_context = webkit_web_frame_get_global_context(im->web_frame); im->js_global = JSContextGetGlobalObject(im->js_context); webkit_web_view_load_uri (WEBKIT_WEB_VIEW(im->web_view), "file://" DATA_DIR "/webkit/im/im.html"); - - - - _this = im; } GtkWidget * @@ -211,4 +219,34 @@ im_widget_get_type(void) } return im_widget_type; +} + + void +im_widget_display (callable_obj_t **call) +{ + + /* Work with a copy of the object */ + callable_obj_t *tmp = *call; + + /* Use the widget for this specific call, if exists */ + IMWidget *im = IM_WIDGET (tmp->_im_widget); + + if (!im) { + g_print ("creating the im widget for this call\n"); + /* Create the im object */ + im = im_widget_new (); + tmp->_im_widget = im; + /* Update the call */ + *call = tmp; + im->call = *call; + + /* Add it to the main instant messaging window */ + gchar *label = get_peer_information (tmp); + im_window_add (im, label); + } + else { + g_print ("im widget exists for this call\n"); + im_window_show (); + } + } diff --git a/sflphone-client-gnome/src/widget/imwidget.h b/sflphone-client-gnome/src/widget/imwidget.h index 7a250b43f8046710eeea75049302b2946c099321..b5e80b27df6eadb3c40ce4b64e16babd4e4b0a79 100644 --- a/sflphone-client-gnome/src/widget/imwidget.h +++ b/sflphone-client-gnome/src/widget/imwidget.h @@ -63,6 +63,13 @@ struct _IMWidgetClass { GtkContainerClass parent_class; }; + +/* + * Display the instant messaging interface for this call. + * If it has not been created yet, create it and attached it to the imWindow + */ +void im_widget_display (callable_obj_t**); + GType im_widget_get_type(void) G_GNUC_CONST; GtkWidget *im_widget_new(void); void im_widget_add_message (callable_obj_t *c, const gchar *message); diff --git a/sflphone-client-gnome/webkit/Makefile.am b/sflphone-client-gnome/webkit/Makefile.am index 7d546f48406ade69060b6c86cbe9a085013c8e6c..6ef49f61b19f88fcbb257a9e1ffe4316c21de7bb 100644 --- a/sflphone-client-gnome/webkit/Makefile.am +++ b/sflphone-client-gnome/webkit/Makefile.am @@ -8,4 +8,5 @@ imdir = $(webkitdir)/im im_DATA = im/im.js \ im/im.html \ im/im.css \ - im/sflphone.png + im/sflphone.png \ + im/chat_info.png diff --git a/sflphone-client-gnome/webkit/im/chat_info.png b/sflphone-client-gnome/webkit/im/chat_info.png new file mode 100644 index 0000000000000000000000000000000000000000..07d3ac7940b2817de5f0497975c883a6c416dd55 Binary files /dev/null and b/sflphone-client-gnome/webkit/im/chat_info.png differ diff --git a/sflphone-client-gnome/webkit/im/im.css b/sflphone-client-gnome/webkit/im/im.css index 5058075b0e2016aaa84e20da4017960bc8c9bb1a..a234d411e9239846c4e4cc7ee9b661d5dd510d6e 100644 --- a/sflphone-client-gnome/webkit/im/im.css +++ b/sflphone-client-gnome/webkit/im/im.css @@ -7,6 +7,7 @@ margin: 20px; overflow: auto; font-size: 0.95em; +clear: both; } * { @@ -22,7 +23,16 @@ body { background: #fbfdfe url(sflphone.png) no-repeat fixed bottom right; } -.peername { +.author { color: #3578B1; font-weight: bold; } + +#call-info { + margin: 40px; +height: 96px; + background: url(chat_info.png) no-repeat center left; + padding: 20px 20px 20px 100px; + border: 2px solid #dedede; + -webkit-border-radius: 25px; +} diff --git a/sflphone-client-gnome/webkit/im/im.html b/sflphone-client-gnome/webkit/im/im.html index cb7e025185417ad01ceff8274fb8ba8e8e862375..ee3a5d55842c5b4665fe92154944e5f52cf147d3 100644 --- a/sflphone-client-gnome/webkit/im/im.html +++ b/sflphone-client-gnome/webkit/im/im.html @@ -5,8 +5,13 @@ </head> <body> <div class='page'> - <div id="call-info"></div> - <div id="messages"></div> + <div id="call-info"> + <h2> Calling <span id='peer-number'></span></h2> + <p>Nom: <span id='peer-name'></span></p> + <p>Plus: <span id='peer-info'></span></p> + </div> + <div id="messages"> + </div> </div> </body> </html> diff --git a/sflphone-client-gnome/webkit/im/im.js b/sflphone-client-gnome/webkit/im/im.js index be53a4b08242d1cb14dfa093b07f7bfbee5725cd..45642b0ce34b9414134bd75bac9e86062ae4690d 100644 --- a/sflphone-client-gnome/webkit/im/im.js +++ b/sflphone-client-gnome/webkit/im/im.js @@ -23,12 +23,16 @@ function add_message (message, peer_name, peer_number, peer_info) } var msgBody = document.getElementById ('messages'); - msgBody.innerHTML = msgBody.innerHTML + '<div class="message">' + '<span class="peername">' + display_name + ': </span>' + '<span class="text">' + linkify (message) + '</span></div>' ; + msgBody.innerHTML = msgBody.innerHTML + '<div class="message">' + '<span class="author">' + display_name + ': </span>' + '<p class="text">' + linkify (message) + '</p></div>' ; } function add_call_info_header (peer_name, peer_number, peer_info) { - var infoBody = document.getElementById ('call-info'); - infoBody.innerHTML = '<h2>Calling ' + peer_number + '</h2><p>' + peer_info + '</p></h4>'; + var peerNumber = document.getElementById ('peer-number'); + var peerName = document.getElementById ('peer-name'); + var peerInfo = document.getElementById ('peer-info'); + peerNumber.innerHTML = peer_number; + peerName.innerHTML = peer_name; + peerInfo.innerHTML = peer_info; }