408 lines
9.1 KiB
C
408 lines
9.1 KiB
C
/*
|
|
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
|
|
*/
|
|
#include "e.h"
|
|
|
|
/* currently default bind is alt+` buf alt+space has been suggested */
|
|
|
|
/* local subsystem functions */
|
|
|
|
static void _e_exebuf_matches_clear(void);
|
|
static void _e_exebuf_update(void);
|
|
static void _e_exebuf_exec(void);
|
|
static void _e_exebuf_next(void);
|
|
static void _e_exebuf_prev(void);
|
|
static void _e_exebuf_complete(void);
|
|
static void _e_exebuf_backspace(void);
|
|
static void _e_exebuf_matches_update(void);
|
|
static int _e_exebuf_cb_key_down(void *data, int type, void *event);
|
|
static int _e_exebuf_cb_mouse_down(void *data, int type, void *event);
|
|
static int _e_exebuf_cb_mouse_up(void *data, int type, void *event);
|
|
static int _e_exebuf_cb_mouse_wheel(void *data, int type, void *event);
|
|
|
|
/* local subsystem globals */
|
|
static E_Popup *exebuf = NULL;
|
|
static Evas_Object *bg_object = NULL;
|
|
static Evas_List *handlers = NULL;
|
|
static Ecore_X_Window input_window = 0;
|
|
static char *cmd_buf = NULL;
|
|
static Evas_List *eap_matches = NULL;
|
|
static Evas_List *exe_matches = NULL;
|
|
static E_App *eap_sel = NULL;
|
|
static Ecore_List *exe_list = NULL;
|
|
|
|
#define EXEBUFLEN 2048
|
|
|
|
/* externally accessible functions */
|
|
int
|
|
e_exebuf_init(void)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
e_exebuf_shutdown(void)
|
|
{
|
|
e_exebuf_hide();
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
e_exebuf_show(E_Zone *zone)
|
|
{
|
|
Evas_Object *o;
|
|
int x, y, w, h;
|
|
Evas_Coord mw, mh;
|
|
|
|
E_OBJECT_CHECK_RETURN(zone, 0);
|
|
E_OBJECT_TYPE_CHECK_RETURN(zone, E_ZONE_TYPE, 0);
|
|
|
|
if (exebuf) return 0;
|
|
|
|
input_window = ecore_x_window_input_new(zone->container->win, 0, 0, 1, 1);
|
|
ecore_x_window_show(input_window);
|
|
e_grabinput_get(input_window, 0, input_window);
|
|
|
|
x = zone->x + 20;
|
|
y = zone->y + 20 + ((zone->h - 20 - 20 - 20) / 2);
|
|
w = zone->w - 20 - 20;
|
|
h = 20;
|
|
|
|
exebuf = e_popup_new(zone, x, y, w, h);
|
|
if (!exebuf) return 0;
|
|
|
|
cmd_buf = malloc(EXEBUFLEN);
|
|
if (!cmd_buf)
|
|
{
|
|
e_object_del(E_OBJECT(exebuf));
|
|
return 0;
|
|
}
|
|
cmd_buf[0] = 0;
|
|
|
|
e_popup_layer_set(exebuf, 255);
|
|
evas_event_freeze(exebuf->evas);
|
|
o = edje_object_add(exebuf->evas);
|
|
bg_object = o;
|
|
e_theme_edje_object_set(o, "base/theme/exebuf",
|
|
"widgets/exebuf/main");
|
|
edje_object_part_text_set(o, "label", cmd_buf);
|
|
edje_object_size_min_calc(o, &mw, &mh);
|
|
|
|
x = zone->x + 20;
|
|
y = zone->y + 20 + ((zone->h - 20 - 20 - mh) / 2);
|
|
w = zone->w - 20 - 20;
|
|
h = mh;
|
|
|
|
e_popup_move_resize(exebuf, x, y, w, h);
|
|
evas_object_move(o, 0, 0);
|
|
evas_object_resize(o, w, h);
|
|
evas_object_show(o);
|
|
e_popup_edje_bg_object_set(exebuf, o);
|
|
|
|
|
|
evas_event_thaw(exebuf->evas);
|
|
|
|
handlers = evas_list_append
|
|
(handlers, ecore_event_handler_add
|
|
(ECORE_X_EVENT_KEY_DOWN, _e_exebuf_cb_key_down, NULL));
|
|
handlers = evas_list_append
|
|
(handlers, ecore_event_handler_add
|
|
(ECORE_X_EVENT_MOUSE_BUTTON_DOWN, _e_exebuf_cb_mouse_down, NULL));
|
|
handlers = evas_list_append
|
|
(handlers, ecore_event_handler_add
|
|
(ECORE_X_EVENT_MOUSE_BUTTON_UP, _e_exebuf_cb_mouse_up, NULL));
|
|
handlers = evas_list_append
|
|
(handlers, ecore_event_handler_add
|
|
(ECORE_X_EVENT_MOUSE_WHEEL, _e_exebuf_cb_mouse_wheel, NULL));
|
|
|
|
exe_list = ecore_file_app_list();
|
|
|
|
e_popup_show(exebuf);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
e_exebuf_hide(void)
|
|
{
|
|
if (!exebuf) return;
|
|
|
|
evas_event_freeze(exebuf->evas);
|
|
e_popup_hide(exebuf);
|
|
evas_object_del(bg_object);
|
|
bg_object = NULL;
|
|
evas_event_thaw(exebuf->evas);
|
|
e_object_del(E_OBJECT(exebuf));
|
|
exebuf = NULL;
|
|
while (handlers)
|
|
{
|
|
ecore_event_handler_del(handlers->data);
|
|
handlers = evas_list_remove_list(handlers, handlers);
|
|
}
|
|
ecore_x_window_del(input_window);
|
|
e_grabinput_release(input_window, input_window);
|
|
input_window = 0;
|
|
free(cmd_buf);
|
|
cmd_buf = NULL;
|
|
if (exe_list)
|
|
{
|
|
ecore_list_destroy(exe_list);
|
|
exe_list = NULL;
|
|
}
|
|
_e_exebuf_matches_clear();
|
|
}
|
|
|
|
/* local subsystem functions */
|
|
|
|
static void
|
|
_e_exebuf_matches_clear(void)
|
|
{
|
|
while (eap_matches)
|
|
{
|
|
e_object_unref(E_OBJECT(eap_matches->data));
|
|
eap_matches = evas_list_remove_list(eap_matches, eap_matches);
|
|
}
|
|
while (exe_matches)
|
|
{
|
|
free(exe_matches->data);
|
|
exe_matches = evas_list_remove_list(exe_matches, exe_matches);
|
|
}
|
|
eap_sel = NULL;
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_update(void)
|
|
{
|
|
edje_object_part_text_set(bg_object, "label", cmd_buf);
|
|
/* FIXME: if cmd_buf is an exact match for an eap or exe display an icon
|
|
* to show it is */
|
|
/* FIXME: display match lists. if match is exat match for cmd_buf dont
|
|
* list it as it will be matched and indicated
|
|
*/
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_exec(void)
|
|
{
|
|
if (eap_sel)
|
|
e_zone_app_exec(exebuf->zone, eap_sel);
|
|
else
|
|
e_zone_exec(exebuf->zone, cmd_buf);
|
|
|
|
e_exebuf_hide();
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_next(void)
|
|
{
|
|
char *exe = NULL;
|
|
|
|
if (exe_matches) exe = exe_matches->data;
|
|
if (exe)
|
|
{
|
|
if (strlen(exe < (EXEBUFLEN - 1)))
|
|
{
|
|
strcpy(cmd_buf, exe);
|
|
_e_exebuf_update();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_prev(void)
|
|
{
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_complete(void)
|
|
{
|
|
char common[EXEBUFLEN], *exe;
|
|
Evas_List *l;
|
|
int orig_len, common_len, exe_len, next_char, val, pos, matches;
|
|
|
|
strcpy(common, cmd_buf);
|
|
orig_len = common_len = strlen(common);
|
|
matches = 1;
|
|
while (matches)
|
|
{
|
|
next_char = 0;
|
|
matches = 0;
|
|
for (l = exe_matches; l; l = l->next)
|
|
{
|
|
matches = 1;
|
|
exe = l->data;
|
|
exe_len = strlen(exe);
|
|
if (exe_len > common_len)
|
|
{
|
|
val = 0;
|
|
pos = evas_string_char_next_get(exe, common_len, &val);
|
|
if (!next_char)
|
|
next_char = val;
|
|
else if (next_char != val)
|
|
{
|
|
matches = 0;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
matches = 0;
|
|
break;
|
|
}
|
|
}
|
|
if (matches) common_len++;
|
|
}
|
|
if ((exe) && (orig_len < common_len) && (common_len < (EXEBUFLEN - 1)))
|
|
{
|
|
strncpy(cmd_buf, exe, common_len);
|
|
cmd_buf[common_len] = 0;
|
|
_e_exebuf_update();
|
|
_e_exebuf_matches_update();
|
|
}
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_backspace(void)
|
|
{
|
|
int len, val, pos;
|
|
|
|
len = strlen(cmd_buf);
|
|
if (len > 0)
|
|
{
|
|
pos = evas_string_char_prev_get(cmd_buf, len, &val);
|
|
if ((pos < len) && (pos >= 0))
|
|
{
|
|
cmd_buf[pos] = 0;
|
|
_e_exebuf_update();
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
_e_exebuf_matches_update(void)
|
|
{
|
|
char *path, *file, buf[4096];
|
|
Evas_Hash *added = NULL;
|
|
|
|
/* how to match:
|
|
*
|
|
* eap_matches (above the exebuf)
|
|
* match cmd_buf* for all eap->exe fields
|
|
* match cmd_buf* for all eap->name fields
|
|
* match *cmd_buf* for all eap->generic fields
|
|
* match *cmd_buf* for all eap->comment fields
|
|
*
|
|
* exe_matches (below the exebuf)
|
|
* match cmd_buf* for all executables in $PATH (exclude duplicates in eap_matches)
|
|
*/
|
|
_e_exebuf_matches_clear();
|
|
snprintf(buf, sizeof(buf), "%s*", cmd_buf);
|
|
if (exe_list)
|
|
{
|
|
ecore_list_goto_first(exe_list);
|
|
while ((path = ecore_list_next(exe_list)) != NULL)
|
|
{
|
|
file = ecore_file_get_file(path);
|
|
if (file)
|
|
{
|
|
if (e_util_glob_match(file, buf))
|
|
{
|
|
if (!evas_hash_find(added, file))
|
|
{
|
|
exe_matches = evas_list_append(exe_matches, strdup(file));
|
|
added = evas_hash_direct_add(added, file, file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (added) evas_hash_free(added);
|
|
}
|
|
|
|
static int
|
|
_e_exebuf_cb_key_down(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Key_Down *ev;
|
|
|
|
ev = event;
|
|
if (ev->win != input_window) return 1;
|
|
if (!strcmp(ev->keysymbol, "Up"))
|
|
_e_exebuf_prev();
|
|
else if (!strcmp(ev->keysymbol, "Down"))
|
|
_e_exebuf_next();
|
|
else if (!strcmp(ev->keysymbol, "Prior"))
|
|
_e_exebuf_prev();
|
|
else if (!strcmp(ev->keysymbol, "Next"))
|
|
_e_exebuf_next();
|
|
else if (!strcmp(ev->keysymbol, "Left"))
|
|
_e_exebuf_prev();
|
|
else if (!strcmp(ev->keysymbol, "Right"))
|
|
_e_exebuf_complete();
|
|
else if (!strcmp(ev->keysymbol, "Tab"))
|
|
_e_exebuf_complete();
|
|
else if (!strcmp(ev->keysymbol, "Return"))
|
|
_e_exebuf_exec();
|
|
else if (!strcmp(ev->keysymbol, "KP_Enter"))
|
|
_e_exebuf_exec();
|
|
else if (!strcmp(ev->keysymbol, "Escape"))
|
|
e_exebuf_hide();
|
|
else if (!strcmp(ev->keysymbol, "BackSpace"))
|
|
_e_exebuf_backspace();
|
|
else if (!strcmp(ev->keysymbol, "Delete"))
|
|
_e_exebuf_backspace();
|
|
else
|
|
{
|
|
if (ev->key_compose)
|
|
{
|
|
if ((strlen(cmd_buf) < (EXEBUFLEN - strlen(ev->key_compose))))
|
|
{
|
|
strcat(cmd_buf, ev->key_compose);
|
|
_e_exebuf_update();
|
|
_e_exebuf_matches_update();
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_exebuf_cb_mouse_down(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Mouse_Button_Down *ev;
|
|
|
|
ev = event;
|
|
if (ev->win != input_window) return 1;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_exebuf_cb_mouse_up(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Mouse_Button_Up *ev;
|
|
|
|
ev = event;
|
|
if (ev->win != input_window) return 1;
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
_e_exebuf_cb_mouse_wheel(void *data, int type, void *event)
|
|
{
|
|
Ecore_X_Event_Mouse_Wheel *ev;
|
|
|
|
ev = event;
|
|
if (ev->win != input_window) return 1;
|
|
if (ev->z < 0) /* up */
|
|
{
|
|
int i;
|
|
|
|
for (i = ev->z; i < 0; i++) e_exebuf_hide();
|
|
}
|
|
else if (ev->z > 0) /* down */
|
|
{
|
|
int i;
|
|
|
|
for (i = ev->z; i > 0; i--) e_exebuf_hide();
|
|
}
|
|
return 1;
|
|
}
|