#include "e_mod_main.h" #include /* Forward declarations */ static E_Gadcon_Client *_gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style); static void _gc_shutdown(E_Gadcon_Client *gcc); static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient); static const char *_gc_label(const E_Gadcon_Client_Class *client_class); static Evas_Object *_gc_icon(const E_Gadcon_Client_Class *client_class, Evas *evas); static const char *_gc_id_new(const E_Gadcon_Client_Class *client_class); static void _gadget_mouse_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info); static void _gadget_update(Instance *inst); static Eina_Bool _gadget_update_timer_cb(void *data); /* Gadcon class definition */ static const E_Gadcon_Client_Class _gc_class = { GADCON_CLIENT_CLASS_VERSION, "iwd", { _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL, NULL }, E_GADCON_CLIENT_STYLE_PLAIN }; /* Global gadcon provider */ static E_Gadcon_Client_Class *gadcon_class = NULL; /* Initialize gadget subsystem */ void e_iwd_gadget_init(void) { DBG("Initializing gadget"); gadcon_class = (E_Gadcon_Client_Class *)&_gc_class; e_gadcon_provider_register(gadcon_class); } /* Shutdown gadget subsystem */ void e_iwd_gadget_shutdown(void) { DBG("Shutting down gadget"); if (gadcon_class) { e_gadcon_provider_unregister(gadcon_class); gadcon_class = NULL; } } /* Gadcon init */ static E_Gadcon_Client * _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style) { Instance *inst; E_Gadcon_Client *gcc; Evas_Object *o; DBG("Creating gadget instance"); inst = E_NEW(Instance, 1); if (!inst) return NULL; /* Create edje object */ o = edje_object_add(gc->evas); /* Load theme */ char theme_path[PATH_MAX]; snprintf(theme_path, sizeof(theme_path), "%s/e-module-iwd.edj", e_module_dir_get(iwd_mod->module)); if (!edje_object_file_set(o, theme_path, "e/modules/iwd/main")) { /* Theme not found, use simple colored rectangle as fallback */ WRN("Failed to load theme from %s", theme_path); evas_object_color_set(o, 100, 150, 200, 255); } evas_object_show(o); /* Pass the object directly to e_gadcon_client_new */ gcc = e_gadcon_client_new(gc, name, id, style, o); if (!gcc) { evas_object_del(o); E_FREE(inst); return NULL; } gcc->data = inst; inst->gcc = gcc; inst->icon = o; inst->gadget = o; /* Add mouse event handler */ evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _gadget_mouse_down_cb, inst); /* Get first available device */ Eina_List *devices = iwd_devices_get(); if (devices && eina_list_count(devices) > 0) { inst->device = eina_list_data_get(devices); DBG("Using device: %s", inst->device->name ? inst->device->name : inst->device->path); } else { DBG("No Wi-Fi devices available"); } /* Start update timer */ inst->update_timer = ecore_timer_add(2.0, _gadget_update_timer_cb, inst); _gadget_update(inst); /* Add to module instances */ if (iwd_mod) iwd_mod->instances = eina_list_append(iwd_mod->instances, inst); return gcc; } /* Gadcon shutdown */ static void _gc_shutdown(E_Gadcon_Client *gcc) { Instance *inst; DBG("Destroying gadget instance"); if (!(inst = gcc->data)) return; /* Remove from module instances */ if (iwd_mod) iwd_mod->instances = eina_list_remove(iwd_mod->instances, inst); /* Delete popup if open */ if (inst->popup) { iwd_popup_del(inst); } /* Stop timer */ if (inst->update_timer) { ecore_timer_del(inst->update_timer); inst->update_timer = NULL; } /* Delete icon */ if (inst->icon) evas_object_del(inst->icon); E_FREE(inst); } /* Gadcon orient */ static void _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient EINA_UNUSED) { Instance *inst; Evas_Coord mw, mh; inst = gcc->data; if (!inst || !inst->icon) return; mw = 0; mh = 0; edje_object_size_min_get(inst->icon, &mw, &mh); if ((mw < 1) || (mh < 1)) edje_object_size_min_calc(inst->icon, &mw, &mh); if (mw < 4) mw = 4; if (mh < 4) mh = 4; e_gadcon_client_aspect_set(gcc, mw, mh); e_gadcon_client_min_size_set(gcc, mw, mh); } /* Gadcon label */ static const char * _gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED) { return "IWD Wi-Fi"; } /* Gadcon icon */ static Evas_Object * _gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas) { Evas_Object *o; char theme_path[PATH_MAX]; o = edje_object_add(evas); /* Try to load theme */ if (iwd_mod && iwd_mod->module) { snprintf(theme_path, sizeof(theme_path), "%s/e-module-iwd.edj", e_module_dir_get(iwd_mod->module)); if (!edje_object_file_set(o, theme_path, "e/modules/iwd/main")) { /* Fallback to simple colored box */ evas_object_color_set(o, 100, 150, 200, 255); evas_object_resize(o, 16, 16); } } else { /* Fallback if module not initialized yet */ evas_object_color_set(o, 100, 150, 200, 255); evas_object_resize(o, 16, 16); } evas_object_show(o); return o; } /* Generate new ID */ static const char * _gc_id_new(const E_Gadcon_Client_Class *client_class) { static char buf[128]; Mod *mod = iwd_mod; snprintf(buf, sizeof(buf), "%s.%d", client_class->name, mod ? eina_list_count(mod->instances) + 1 : 1); return buf; } /* Mouse down callback */ static void _gadget_mouse_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info) { Instance *inst = data; Evas_Event_Mouse_Down *ev = event_info; if (!inst) { e_util_dialog_show("Debug", "Instance is NULL!"); return; } if (ev->button == 1) /* Left click */ { INF("Gadget clicked - popup=%p device=%p", inst->popup, inst->device); if (inst->popup) { /* Close popup */ INF("Closing popup"); iwd_popup_del(inst); } else { /* Open popup */ INF("Opening popup"); iwd_popup_new(inst); /* Debug: Check if popup was created */ if (!inst->popup) { ERR("Failed to create popup!"); e_util_dialog_show("IWD Debug", "Popup creation failed.
" "Check if iwd is running and wireless device exists."); } } } } /* Update gadget icon and tooltip */ static void _gadget_update(Instance *inst) { char buf[256]; if (!inst) return; /* Update tooltip */ if (inst->device) { if (inst->device->state && strcmp(inst->device->state, "connected") == 0) { snprintf(buf, sizeof(buf), "IWD Wi-Fi\nConnected: %s\nSignal: %s", inst->device->name ? inst->device->name : "Unknown", inst->device->connected_network ? "Good" : ""); } else if (inst->device->state && strcmp(inst->device->state, "connecting") == 0) { snprintf(buf, sizeof(buf), "IWD Wi-Fi\nConnecting..."); } else { snprintf(buf, sizeof(buf), "IWD Wi-Fi\nDisconnected"); } } else { snprintf(buf, sizeof(buf), "IWD Wi-Fi\nNo device"); } /* Update icon appearance using Edje signals */ extern IWD_State iwd_state_get(void); IWD_State state = iwd_state_get(); const char *file = NULL; /* Check if theme is loaded */ if (inst->icon) { edje_object_file_get(inst->icon, &file, NULL); } if (inst->icon && file) { /* Icon has theme loaded, use signals */ switch (state) { case IWD_STATE_CONNECTED: edje_object_signal_emit(inst->icon, "e,state,connected", "e"); edje_object_signal_emit(inst->icon, "e,signal,show", "e"); break; case IWD_STATE_CONNECTING: edje_object_signal_emit(inst->icon, "e,state,connecting", "e"); edje_object_signal_emit(inst->icon, "e,signal,hide", "e"); break; case IWD_STATE_ERROR: edje_object_signal_emit(inst->icon, "e,state,error", "e"); edje_object_signal_emit(inst->icon, "e,signal,hide", "e"); break; default: edje_object_signal_emit(inst->icon, "e,state,disconnected", "e"); edje_object_signal_emit(inst->icon, "e,signal,hide", "e"); break; } } else { /* Fallback to color changes if no theme */ if (inst->device && inst->device->state) { if (strcmp(inst->device->state, "connected") == 0) evas_object_color_set(inst->icon, 100, 200, 100, 255); /* Green */ else if (strcmp(inst->device->state, "connecting") == 0) evas_object_color_set(inst->icon, 200, 200, 100, 255); /* Yellow */ else evas_object_color_set(inst->icon, 150, 150, 150, 255); /* Gray */ } else { evas_object_color_set(inst->icon, 200, 100, 100, 255); /* Red - no device */ } } } /* Update timer callback */ static Eina_Bool _gadget_update_timer_cb(void *data) { Instance *inst = data; _gadget_update(inst); return ECORE_CALLBACK_RENEW; }