diff --git a/contrib/gtk2/gtk2client.cpp b/contrib/gtk2/gtk2client.cpp index 869e2072..a2b70ae3 100644 --- a/contrib/gtk2/gtk2client.cpp +++ b/contrib/gtk2/gtk2client.cpp @@ -26,6 +26,7 @@ #include "gtk2client.h" #include +#include using namespace TelEngine; @@ -133,6 +134,23 @@ static bool validPos(int x, int y) return (-10000 < x) && (x < 10000) && (-10000 < y) && (y < 10000); } +static void makeUserSignal(GtkWidget* wid) +{ + static guint action = (guint)-1; + if ((action != (guint)-1) || !wid) + return; + static GType type = G_TYPE_STRING; + action = g_signal_newv("user_action", + GTK_WIDGET_TYPE(wid), + (GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION), + NULL, + NULL,NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, + 1, &type); + DDebug(GTKDriver::self(),DebugInfo,"Created user signal %u",action); +} + static gboolean gtkIdleCb(gpointer dat) { if (dat) { @@ -151,7 +169,7 @@ static gboolean debugCbInfo(GtkWidget* wid) gchar* wcp = NULL; gtk_widget_path(wid,NULL,&wp,NULL); gtk_widget_class_path(wid,NULL,&wcp,NULL); - Debug(GTKDriver::self(),DebugAll,"debugCbInfo widget %p path '%s' class path '%s'", + Debug(GTKDriver::self(),DebugNote,"debugCbInfo widget %p path '%s' class path '%s'", wid,wp,wcp); g_free(wp); g_free(wcp); @@ -281,6 +299,16 @@ static GtkWidget* getListItem(GtkList* lst, const String& item) return ret; } +static gboolean widgetCbUser(GtkWidget* wid, const gchar* str) +{ + DDebug(GTKDriver::self(),DebugAll,"gtkUserAction widget %p action '%s'",wid,str); + if (GTKClient::changing()) + return FALSE; + if (s_clickInfo) + debugCbInfo(wid); + return GTKClient::self() && GTKClient::self()->action(getWidgetWindow(wid),str); +} + static gboolean widgetCbAction(GtkWidget* wid, gpointer dat) { Debug(GTKDriver::self(),DebugAll,"widgetCbAction(%p,%p)",wid,dat); @@ -811,10 +839,11 @@ void Widget::destroyCb(GtkObject* obj, gpointer dat) GTKWindow::GTKWindow(const char* id, bool decorated, Layout layout) : Window(id), m_decorated(decorated), m_dragable(false), m_layout(layout), - m_widget(0), m_filler(0), m_state(0), + m_widget(0), m_filler(0), m_group(0), m_state(0), m_posX(INVALID_POS), m_posY(INVALID_POS), m_sizeW(0), m_sizeH(0) { m_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); + makeUserSignal(m_widget); g_object_set_data((GObject*)m_widget,"Yate::Window",this); gtk_window_set_role((GtkWindow*)m_widget,id); // gtk_window_set_type_hint((GtkWindow*)m_widget,GDK_WINDOW_TYPE_HINT_DIALOG); @@ -827,6 +856,7 @@ GTKWindow::GTKWindow(const char* id, bool decorated, Layout layout) g_signal_connect(G_OBJECT(m_widget),"configure_event",G_CALLBACK(windowCbConfig),this); g_signal_connect(G_OBJECT(m_widget),"window_state_event",G_CALLBACK(windowCbState),this); g_signal_connect(G_OBJECT(m_widget),"show_help",G_CALLBACK(widgetCbHelp),this); + g_signal_connect(G_OBJECT(m_widget),"user_action",G_CALLBACK(widgetCbUser),this); #ifdef XDEBUG g_signal_connect(G_OBJECT(m_widget),"event",G_CALLBACK(windowCbEvent),this); #endif @@ -1075,7 +1105,12 @@ void GTKWindow::init() title(s_cfg.getValue(m_id,"title",m_id)); m_master = s_cfg.getBoolValue(m_id,"master"); m_popup = s_cfg.getBoolValue(m_id,"popup"); - if (!(m_master || m_decorated)) + if (m_master || m_decorated) { + // put these windows in their own group + m_group = gtk_window_group_new(); + gtk_window_group_add_window(m_group,(GtkWindow*)m_widget); + } + else gtk_window_set_type_hint((GtkWindow*)m_widget,GDK_WINDOW_TYPE_HINT_TOOLBAR); m_posX = s_save.getIntValue(m_id,"x",m_posX); m_posY = s_save.getIntValue(m_id,"y",m_posY); @@ -1209,6 +1244,8 @@ void GTKWindow::setOver(const Window* parent) { GTKWindow* gwnd = YOBJECT(GTKWindow,parent); if (gwnd) { + if (gwnd->group()) + gtk_window_group_add_window(gwnd->group(),GTK_WINDOW(m_widget)); gtk_window_set_transient_for(GTK_WINDOW(m_widget),GTK_WINDOW(gwnd->widget())); if (gwnd->prepare() && validPos(gwnd->m_posX,gwnd->m_posY)) move(gwnd->m_posX + (gwnd->m_sizeW - m_sizeW) / 2, diff --git a/contrib/gtk2/gtk2client.h b/contrib/gtk2/gtk2client.h index 2e4a9930..4ee8e3f5 100644 --- a/contrib/gtk2/gtk2client.h +++ b/contrib/gtk2/gtk2client.h @@ -173,6 +173,8 @@ public: { m_state = gdkState; } inline bool dragable() const { return m_dragable; } + inline GtkWindowGroup* group() const + { return m_group; } bool prepare(); bool restore(); static bool setText(GtkWidget* wid, const String& text); @@ -196,6 +198,7 @@ protected: int m_layout; GtkWidget* m_widget; GtkWidget* m_filler; + GtkWindowGroup* m_group; String m_tabName; int m_state; gint m_posX; diff --git a/engine/Client.cpp b/engine/Client.cpp index e9496430..dd7491c2 100644 --- a/engine/Client.cpp +++ b/engine/Client.cpp @@ -989,6 +989,11 @@ bool Client::action(Window* wnd, const String& name) wnd->hide(); return ok; } + if (name.startsWith("help_show:")) { + Window* help = getWindow("help"); + if (help) + wnd = help; + } if (name == "call" || name == "callto") { String target; getText("callto",target,wnd); diff --git a/modules/skin/tabbed/gtk2client.rc b/modules/skin/tabbed/gtk2client.rc index 10dd8496..72c39c9e 100644 --- a/modules/skin/tabbed/gtk2client.rc +++ b/modules/skin/tabbed/gtk2client.rc @@ -49,18 +49,25 @@ style "caption" { bg[NORMAL] = { 0.93, 0.95, 0.96 } } -binding "help" { - bind "F1" { - "show-help" (0,2,0) - "debug-msg" ("Help requested") - } +binding "help_main" { + bind "F1" { "user-action" ("help_show:0") } +} + +binding "help_p1" { + bind "F1" { "user-action" ("help_show:1") } +} + +binding "help_p2" { + bind "F1" { "user-action" ("help_show:2") } } widget "gtk-tooltips" style "tips" widget "gtk-tooltips*GtkLabel" style "tips" +widget "addrbook" binding "help_p1" +widget "account" binding "help_p2" +class "GtkWindow" binding "help_main" class "GtkWindow" style "window" -class "GtkWindow" binding "help" class "GtkWidget" style "window" widget_class "GtkWindow.GtkFrame" style "border" class "GtkButton" style "button"