terminology/src/bin/app_server.c

426 lines
11 KiB
C

#include "private.h"
#include <Elementary.h>
#include "main.h"
#include "termio.h"
#include "app_server_eet.h"
#if (ELM_VERSION_MAJOR > 1) || (ELM_VERSION_MINOR >= 8)
static Elm_App_Server *_server = NULL;
static Eina_Bool _ignore_term_add = EINA_FALSE;
static Terminology_Item *views_eet = NULL;
static void
_user_config_file_path_build(char *dir, unsigned int size, const char *id)
{
const char *home = getenv("HOME");
if (!home)
home = "";
snprintf(dir, size, "%s/.terminology/", home);
if (!ecore_file_is_dir(dir))
ecore_file_mkpath(dir);
snprintf(dir, size, "%s/.terminology/%s", home, id);
}
void
app_server_term_del(Evas_Object *term)
{
Elm_App_Server_View *view;
const char *id;
view = evas_object_data_del(term, "app_view");
if (!view)
return;
eo_do(view, elm_app_server_view_id_get(&id));
terminology_item_term_entries_del(views_eet, id);
eo_del(view);
}
static Eina_Bool
_view_closed_cb(void *data, Eo *view,
const Eo_Event_Description *desc EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Term *term = data;
const char *id;
if (term)
{
Evas_Object *term_object;
term_object = main_term_evas_object_get(term);
evas_object_data_del(term_object, "app_view");
main_close(main_win_evas_object_get(main_term_win_get(term)),
term_object);
}
eo_do(view, elm_app_server_view_id_get(&id));
terminology_item_term_entries_del(views_eet, id);
eo_del(view);
return EINA_TRUE;
}
static void
_term_title_changed_cb(void *data, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
const char *title = termio_title_get(obj);
eo_do(data, elm_app_server_view_title_set(title));
}
static void
_term_icon_changed_cb(void *data, Evas_Object *obj,
void *event_info EINA_UNUSED)
{
const char *icon = termio_icon_name_get(obj);
eo_do(data, elm_app_server_view_icon_set(icon));
}
static Eina_Bool
_view_save_cb(void *data EINA_UNUSED,
Eo *view,
const Eo_Event_Description *desc EINA_UNUSED,
void *event_info EINA_UNUSED)
{
char dir[PATH_MAX];
Evas_Object *term_object;
const char *id;
Term_Item *term_eet;
term_object = main_term_evas_object_get(data);
/*
* if we call elm_app_server_save() in some case that the terminology
* will continue run, this data_del will lead to issues.
*/
evas_object_data_del(term_object, "app_view");
termio_cwd_get(term_object, dir, sizeof(dir));
eo_do(view, elm_app_server_view_id_get(&id));
term_eet = terminology_item_term_entries_get(views_eet, id);
if (term_eet)
{
term_item_dir_set(term_eet, dir);
return EINA_TRUE;
}
term_eet = term_item_new(id, dir);
terminology_item_term_entries_add(views_eet, id, term_eet);
return EINA_TRUE;
}
static Eina_Bool
_view_resumed_cb(void *data, Eo *view,
const Eo_Event_Description *desc EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Term *term = data;
Win *wn;
Eina_List **wins;
const char *title, *id;
Evas_Object *term_object;
const char *dir = NULL;
Term_Item *term_eet;
if (term)
{
main_term_focus(term);
return EINA_TRUE;
}
eo_do(_server, eo_base_data_get("wins", (void **)&wins));
wn = eina_list_data_get(*wins);
if (!wn)
{
ERR("There is no window open");
return EINA_TRUE;
}
term = eina_list_data_get(main_win_terms_get(wn));
eo_do(view, elm_app_server_view_id_get(&id));
term_eet = terminology_item_term_entries_get(views_eet, id);
if (term_eet)
{
dir = term_item_dir_get(term_eet);
//not valid data saved
if (!dir || dir[0] != '/')
{
terminology_item_term_entries_del(views_eet, id);
dir = NULL;
}
}
_ignore_term_add = EINA_TRUE;
if (dir)
main_new_with_dir(main_win_evas_object_get(wn),
main_term_evas_object_get(term), dir);
else
main_new(main_win_evas_object_get(wn), main_term_evas_object_get(term));
_ignore_term_add = EINA_FALSE;
//just add term
term = eina_list_last_data_get(main_win_terms_get(wn));
term_object = main_term_evas_object_get(term);
title = termio_title_get(term_object);
evas_object_data_set(term_object, "app_view", view);
eo_do(view, elm_app_server_view_title_set(title),
elm_app_server_view_window_set(
main_win_evas_object_get(main_term_win_get(term))),
eo_event_callback_del(ELM_APP_SERVER_VIEW_EV_CLOSED, _view_closed_cb,
NULL),
eo_event_callback_del(ELM_APP_SERVER_VIEW_EV_RESUMED, _view_resumed_cb,
NULL),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_CLOSED, _view_closed_cb,
term),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_RESUMED, _view_resumed_cb,
term),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_SAVE, _view_save_cb,
term));
evas_object_smart_callback_add(term_object, "title,change",
_term_title_changed_cb, view);
evas_object_smart_callback_add(term_object, "icon,change",
_term_icon_changed_cb, term);
return EINA_TRUE;
}
static Eina_Bool
_server_terminate_cb(void *data, Eo *obj EINA_UNUSED,
const Eo_Event_Description *desc EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Eina_List **wins = data, *l, *l2;
Win *wn;
EINA_LIST_FOREACH_SAFE(*wins, l, l2, wn)
evas_object_del(main_win_evas_object_get(wn));
return EINA_TRUE;
}
void
app_server_shutdown(void)
{
char lock_file[PATH_MAX];
if (!_server)
return;
_user_config_file_path_build(lock_file, sizeof(lock_file), ".lock");
ecore_file_remove(lock_file);
eo_do(_server, elm_app_server_save());
if (views_eet)
{
char eet_dir[PATH_MAX];
_user_config_file_path_build(eet_dir, sizeof(eet_dir), "terms.eet");
terminology_item_save(views_eet, eet_dir);
terminology_item_free(views_eet);
}
app_server_eet_shutdown();
eo_unref(_server);
_server = NULL;
}
void
app_server_win_del_request_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED)
{
Eina_List **wins;
if (!_server)
return;
eo_do(_server, eo_base_data_get("wins", (void **)&wins));
if (eina_list_count(*wins) > 1)
return;
/*
* this way the terms of view are already alive
* and we can get pwd and backlog
*/
app_server_shutdown();
}
static Elm_App_Server_View *
_app_server_term_add(Term *term)
{
Elm_App_Server_View *view;
const char *title;
Evas_Object *term_object;
if (_ignore_term_add)
return NULL;
view = eo_add_custom(ELM_APP_SERVER_VIEW_CLASS, _server,
elm_app_server_view_constructor(NULL));
term_object = main_term_evas_object_get(term);
title = termio_title_get(term_object);
eo_do(view, elm_app_server_view_title_set(title),
elm_app_server_view_window_set(
main_win_evas_object_get(main_term_win_get(term))),
elm_app_server_view_resume(),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_CLOSED,
_view_closed_cb, term),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_RESUMED,
_view_resumed_cb, term),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_SAVE,
_view_save_cb, term));
evas_object_smart_callback_add(term_object, "title,change",
_term_title_changed_cb, view);
evas_object_smart_callback_add(term_object, "icon,change",
_term_icon_changed_cb, term);
evas_object_data_set(term_object, "app_view", view);
return view;
}
void
app_server_term_add(Term *term)
{
Elm_App_Server_View *view;
if (!_server)
return;
view = _app_server_term_add(term);
if (!view)
return;
eo_do(_server, elm_app_server_view_add(view));
}
static Elm_App_Server_View *
_app_server_create_view_cb(Elm_App_Server *server, const Eina_Value *args EINA_UNUSED,
Eina_Stringshare **error_name,
Eina_Stringshare **error_message EINA_UNUSED)
{
Win *wn;
Term *term;
Eina_List **wins;
eo_do(server, eo_base_data_get("wins", (void **)&wins));
wn = eina_list_data_get(*wins);
if (!wn)
{
ERR("There is no window open");
*error_name = eina_stringshare_add("There is no window open");
return NULL;
}
term = eina_list_data_get(main_win_terms_get(wn));
_ignore_term_add = EINA_TRUE;
main_new(main_win_evas_object_get(wn), main_term_evas_object_get(term));
_ignore_term_add = EINA_FALSE;
//Term just added by main_new()
term = eina_list_last_data_get(main_win_terms_get(wn));
return _app_server_term_add(term);
}
static Eina_Bool
_restore_view_cb(void *data)
{
Elm_App_Server_View *view = data;
eo_do(view, elm_app_server_view_resume());
return EINA_FALSE;
}
void
app_server_init(Eina_List **wins, Eina_Bool restore_views)
{
Win *wn;
Eina_Iterator *views;
Elm_App_Server_View *view;
const char *title;
char lock_file[PATH_MAX], eet_dir[PATH_MAX];
FILE *f;
wn = eina_list_data_get(*wins);
if (!wn)
return;
//we only can have one instance of Terminology running app_server
_user_config_file_path_build(lock_file, sizeof(lock_file), ".lock");
if (ecore_file_exists(lock_file))
return;
//create lock file
f = fopen(lock_file, "w");
if (!f)
return;
fprintf(f, "locked");
fclose(f);
app_server_eet_init();
_user_config_file_path_build(eet_dir, sizeof(eet_dir), "terms.eet");
views_eet = terminology_item_load(eet_dir);
if (!views_eet)
views_eet = terminology_item_new(1);
title = elm_win_title_get(main_win_evas_object_get(wn));
_server = eo_add_custom(ELM_APP_SERVER_CLASS, NULL,
elm_app_server_constructor(
"org.enlightenment.Terminology",
_app_server_create_view_cb));
eo_do(_server, elm_app_server_title_set(title),
eo_base_data_set("wins", wins, NULL),
elm_app_server_views_get(&views),
eo_event_callback_add(ELM_APP_SERVER_EV_TERMINATE,
_server_terminate_cb, wins));
//views saved
EINA_ITERATOR_FOREACH(views, view)
{
if (restore_views)
ecore_idler_add(_restore_view_cb, view);
eo_do(view,
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_CLOSED,
_view_closed_cb, NULL),
eo_event_callback_add(ELM_APP_SERVER_VIEW_EV_RESUMED,
_view_resumed_cb, NULL));
}
eina_iterator_free(views);
}
#else
void app_server_init(Eina_List **wins EINA_UNUSED,
Eina_Bool restore_views EINA_UNUSED) {}
void app_server_shutdown(void) {}
void app_server_term_add(Term *term EINA_UNUSED) {}
void app_server_term_del(Evas_Object *term EINA_UNUSED) {}
void app_server_win_del_request_cb(void *data EINA_UNUSED,
Evas_Object *obj EINA_UNUSED,
void *event_info EINA_UNUSED) {}
#endif