GTK.c (10505B)
1 #include <EGong/Interfaces/GTK.h> 2 #include <EGong/Interfaces.h> 3 #include <EGong/Util/Misc.h> 4 #include <EGong/Util/Log.h> 5 #include <EGong/Util/Waiter.h> 6 #include <EGong/Main.h> 7 #include <EGong/Interfaces.h> 8 #include <EGong/Interfaces/GUI.h> 9 #include <gtk/gtk.h> 10 #include <EGong/Util/Config_Compiletime.h> 11 #include <EGong/Util/Config.h> 12 #include <stdlib.h> 13 #ifdef USE_LIBNOTIFY 14 #include <libnotify/notify.h> 15 #endif 16 17 GtkWidget *Egong_if_gtk_root=NULL; 18 GdkPixbuf *EGong_if_gtk_icon=NULL; 19 unsigned short int EGong_if_gtk_have_libnotify=0; 20 21 unsigned int EGong_if_gtk_initialized; 22 struct EGong_if_ptrtbl EGong_if_gtk_ptrtbl={ 23 .setup=&EGong_if_gtk_setup, 24 .cycle=&EGong_if_gtk_cycle, 25 .display=&EGong_if_gtk_display, 26 .shutdown=&EGong_if_gtk_shutdown, 27 .sock_watch=&EGong_gtk_waiter_add, 28 .loop=&EGong_if_gtk_main 29 }; 30 int EGong_if_gtk_main(void){ 31 gtk_main(); 32 return 1; 33 } 34 int EGong_if_gtk_setup(struct EGong_interface *interface){ 35 gtk_init(&EGong_global_argc, &EGong_global_argv); 36 #ifdef USE_LIBNOTIFY 37 if(!notify_init("EGong")){ 38 do_log("Couldn't setup libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 39 } 40 else{ 41 EGong_if_gtk_have_libnotify=1; 42 } 43 #endif 44 GError *err=NULL; 45 EGong_if_gtk_icon=gdk_pixbuf_new_from_file(EGONG_INSTALL_PREFIX"/share/EGong.ico", &err); 46 if(EGong_if_gtk_icon==NULL){ 47 do_log("Couldn't open iconfile", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 48 return EGONG_INTERFACE_RETURN_ERROR; 49 } 50 return EGONG_INTERFACE_RETURN_OK; 51 } 52 int EGong_if_gtk_cycle(struct EGong_interface *interface, String *msg, char **dest){ 53 return EGONG_INTERFACE_RETURN_OK; 54 interface->funcs->cycle=NULL; //Prevent any further execution 55 EGong_interfaces_userstreams--; //GTK takes over the job of cycling the interfaces. 56 gtk_main(); 57 return EGONG_INTERFACE_RETURN_EXIT; 58 } 59 60 int EGong_if_gtk_display_window(struct EGong_interface *interface, const String *msg){ 61 do_log("Displaying message in window", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 62 GtkWidget *win=gtk_message_dialog_new(GTK_WINDOW(Egong_if_gtk_root), (Egong_if_gtk_root==NULL) ? 0 : GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "EGong Nachricht"); 63 if(win==NULL){ 64 do_log("Couldn't create messagebox", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 65 } 66 GtkWidget *img=gtk_image_new_from_pixbuf(EGong_if_gtk_icon); 67 if(img==NULL){ 68 do_log("ERRIR", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 69 } 70 else{ 71 gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(win), img); 72 } 73 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(win), msg->data); 74 g_signal_connect_swapped(GTK_WIDGET(win), "response", G_CALLBACK(gtk_widget_destroy), win); 75 gtk_widget_show_all(GTK_WIDGET(win)); 76 } 77 int EGong_if_gtk_display_notify(struct EGong_interface *interface, const String *msg){ 78 do_log("Displaying message with libnotify", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 79 #ifdef USE_LIBNOTIFY 80 if(EGong_if_gtk_have_libnotify==0){ 81 do_log("Libnotify not initialized", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 82 } 83 NotifyNotification *notify=notify_notification_new("Egong Nachricht", msg->data, NULL); 84 notify_notification_set_image_from_pixbuf(notify, EGong_if_gtk_icon); 85 GError *err=NULL; 86 if(!notify_notification_show(notify, &err)){ 87 do_log("Couldn't display notification", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 88 } 89 #else 90 do_log("Libnotify not compiled in...", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 91 #endif 92 } 93 int EGong_if_gtk_display(struct EGong_interface *interface, const String *msg){ 94 do_log("Displaying message", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 95 if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_NOTIFY)>0){ 96 EGong_if_gtk_display_notify(interface, msg); 97 } 98 if((EGong_global_configuration.gui.destinations&EGONG_CONFIG_GUI_DEST_WINDOW)>0){ 99 EGong_if_gtk_display_window(interface, msg); 100 } 101 return EGONG_INTERFACE_RETURN_OK; 102 } 103 104 int EGong_if_gtk_shutdown(struct EGong_interface *interface){ 105 gtk_main_quit(); 106 return EGONG_INTERFACE_RETURN_OK; 107 } 108 void EGong_if_gtk_tray_popup(GtkStatusIcon *icon, guint button, guint activation_time, gpointer data){ 109 gtk_menu_popup(GTK_MENU(data),NULL,NULL,gtk_status_icon_position_menu, icon, button, activation_time); 110 } 111 void EGong_if_gtk_widget_toggle(GtkWidget *caller){ 112 if(gtk_widget_get_visible(caller)){ 113 gtk_widget_hide_all(caller); 114 } 115 else{ 116 gtk_widget_show_all(caller); 117 } 118 } 119 void EGong_if_gtk_show_element(struct EGong_GUI_item *itm){ 120 gtk_widget_show(GTK_WIDGET(itm->itemptr)); 121 } 122 static void EGong_if_gtk_event_callback(GtkWidget *caller, struct EGong_if_gtk_callbackparam *param){ 123 EGong_GUI_event_callback(param->caller, param->event); 124 } 125 GtkWidget *EGong_if_gtk_create_gui(struct EGong_GUI_item *parent, struct EGong_GUI_item *this){ 126 unsigned int i; 127 GtkWidget *element=NULL; 128 GtkWidget *submenu; 129 struct EGong_GUI_item **children=this->child; 130 char *eventdefault; 131 switch(this->type){ 132 case EGONG_GUI_WINDOW: 133 element=gtk_window_new(GTK_WINDOW_TOPLEVEL); 134 g_signal_connect_swapped(element, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), (gpointer)element); 135 if(this->text!=NULL){ 136 gtk_window_set_title(GTK_WINDOW(element),this->text); 137 } 138 gtk_window_set_icon(GTK_WINDOW(element), EGong_if_gtk_icon); 139 eventdefault="activate-focus"; 140 break; 141 case EGONG_GUI_TEXT: 142 element=gtk_entry_new(); 143 if(this->text!=NULL){ 144 gtk_entry_set_text(GTK_ENTRY(element),this->text); 145 } 146 eventdefault="activate"; 147 break; 148 case EGONG_GUI_TOGGLE_BUTTON: 149 element=(this->text!=NULL) ? gtk_toggle_button_new_with_label(this->text) : gtk_toggle_button_new(); 150 eventdefault="toggled"; 151 break; 152 case EGONG_GUI_BUTTON: 153 element=(this->text!=NULL) ? gtk_button_new_with_label(this->text) : gtk_button_new(); 154 eventdefault="clicked"; 155 break; 156 case EGONG_GUI_LABEL: 157 element=gtk_label_new(this->text); 158 break; 159 case EGONG_GUI_MENU: 160 submenu=element=gtk_menu_new(); 161 break; 162 case EGONG_GUI_HBOX: 163 element=gtk_hbox_new(TRUE, 1); 164 break; 165 case EGONG_GUI_VBOX: 166 element=gtk_vbox_new(TRUE, 1); 167 break; 168 case EGONG_GUI_MENUITEM_IMAGE: 169 case EGONG_GUI_MENUITEM: 170 171 if(this->type==EGONG_GUI_MENUITEM_IMAGE){ 172 gchar *stockid; 173 switch((unsigned int)(intptr_t)this->extra){ 174 case EGUI_MIMG_EXIT: 175 stockid=GTK_STOCK_QUIT; 176 break; 177 } 178 element=gtk_image_menu_item_new_with_label(this->text); 179 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(element),gtk_image_new_from_icon_name((const gchar *)stockid,GTK_ICON_SIZE_MENU)); 180 } 181 else{ 182 element=gtk_menu_item_new_with_label(this->text); 183 } 184 if(this->child!=NULL){ //Menuitem has submenus 185 struct EGong_GUI_item subm={ 186 .type=EGONG_GUI_MENU, .text=NULL, .tooltip=NULL, .child=this->child 187 }; 188 submenu=EGong_if_gtk_create_gui(this, &subm); 189 gtk_menu_item_set_submenu(GTK_MENU_ITEM(element), submenu); 190 children=NULL; //Children have been processed 191 } 192 eventdefault="activate"; 193 break; 194 case EGONG_GUI_SYSTRAY: 195 element=(GtkWidget *)gtk_status_icon_new_from_pixbuf(EGong_if_gtk_icon); 196 eventdefault="activate"; 197 break; 198 default: 199 do_log("Unknown GUI-Type specified", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 200 return NULL; 201 } 202 if(element==NULL){ 203 do_log("Couldn't initialize element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 204 return NULL; 205 } 206 if(this->tooltip!=NULL){ 207 if(this->type==EGONG_GUI_SYSTRAY) gtk_status_icon_set_tooltip(GTK_STATUS_ICON(element),this->tooltip); 208 else gtk_widget_set_tooltip_text(element,this->tooltip); 209 } 210 if(this->events!=NULL){ 211 struct EGong_GUI_event *ev; 212 for(i=0;this->events[i]!=NULL; i++){ 213 struct EGong_if_gtk_callbackparam *param=malloc(sizeof(struct EGong_if_gtk_callbackparam)); 214 param->caller=this; 215 param->event=this->events[i]; 216 g_signal_connect(element, eventdefault, G_CALLBACK(EGong_if_gtk_event_callback), (gpointer)param); 217 } 218 } 219 if(children!=NULL){ 220 GtkWidget *child_widget; 221 for(i=0;children[i]!=NULL; i++){ 222 child_widget=EGong_if_gtk_create_gui(this, children[i]); 223 if(child_widget!=NULL){ 224 if(children[i]->type==EGONG_GUI_WINDOW){ 225 if(this->type==EGONG_GUI_SYSTRAY){ 226 g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(EGong_if_gtk_widget_toggle), child_widget); 227 } 228 else{ 229 g_signal_connect_swapped(GTK_STATUS_ICON(element), "activate", G_CALLBACK(gtk_widget_show_all), child_widget); 230 } 231 } 232 else{ 233 switch(this->type){ 234 case EGONG_GUI_MENU: 235 case EGONG_GUI_MENUITEM: 236 gtk_menu_shell_append(GTK_MENU_SHELL(submenu), child_widget); 237 break; 238 case EGONG_GUI_HBOX: 239 case EGONG_GUI_VBOX: 240 gtk_box_pack_start(GTK_BOX(element), child_widget, TRUE, TRUE, 1); 241 break; 242 case EGONG_GUI_SYSTRAY: 243 if(children[i]->type==EGONG_GUI_MENU){ 244 g_signal_connect(GTK_STATUS_ICON(element), "popup-menu", G_CALLBACK(EGong_if_gtk_tray_popup), child_widget); 245 } 246 else{ 247 do_log("Unknown mapping from systray", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 248 gtk_widget_destroy(GTK_WIDGET(child_widget)); 249 } 250 break; 251 default: 252 do_log("Assigning default", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 253 gtk_container_add(GTK_CONTAINER(element), child_widget); 254 break; 255 } 256 gtk_widget_show(child_widget); 257 } 258 } 259 else{ 260 do_log("Couldn't initialize child Element", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 261 } 262 } 263 } 264 if(parent==NULL&&Egong_if_gtk_root==NULL&&this->type!=EGONG_GUI_SYSTRAY){ 265 Egong_if_gtk_root=element; 266 } 267 this->itemptr=(void *)element; 268 return element; 269 } 270 void *EGong_gtk_get_item_value(struct EGong_GUI_item *itm){ 271 void *ret=NULL; 272 switch(itm->type){ 273 case EGONG_GUI_TEXT: 274 ret=(void *)gtk_entry_get_text(itm->itemptr); 275 break; 276 case EGONG_GUI_WINDOW: 277 ret=(void *)itm->itemptr; 278 break; 279 case EGONG_GUI_TOGGLE_BUTTON: 280 ret=(void *)(intptr_t)(unsigned int)(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(itm->itemptr)) ? 1 : 0); 281 break; 282 default: 283 do_log("Event datasource specified where no data can be obtained", LOG_TYPE_NORMAL, LOG_LEVEL_ERROR); 284 break; 285 } 286 return ret; 287 } 288 void EGong_if_gtk_free_item_value(struct EGong_GUI_item *itm, void *element){ 289 return; 290 } 291 gboolean Egong_waiter_gtk_callback(GIOChannel *source, GIOCondition condition, gpointer data){ 292 if(EGong_interface_cycle()!=0){ 293 EGong_if_gtk_shutdown(NULL); 294 } 295 return G_SOURCE_CONTINUE; 296 } 297 int EGong_gtk_waiter_add(int sock, unsigned short int type){ 298 do_log("Adding sockwatch", LOG_TYPE_NORMAL, LOG_LEVEL_DEBUG); 299 GIOChannel *new=g_io_channel_unix_new(sock); 300 g_io_add_watch(new,G_IO_IN|G_IO_ERR|G_IO_HUP, Egong_waiter_gtk_callback, NULL); 301 return 0; 302 }