terminology can do multi instance now (in a single process). that
means 2 or 3 or more windows == same terminology process. there is a checkbox to turn it on. in theory it CAN do multipe terms within 1 windows, except there's incomplete sizing logic code for hansling step sizing and min size with multielp terms in the same window (imagine u laid them out in a table grid... all we need is a table and pack n terms in and presto.. but the sizing will be "bizarre" at the moment)... if they are packed on top of eachother like a notebook... sure - but no notebook widget and no way to sensibly display and switch... but the code infra now all supports it in theory. this is more about testing and making that infra work. first will probably be a grid layout of some sort because frankly... it's easier. but for now... lets get this multi-instance fun on the table. SVN revision: 81740
This commit is contained in:
parent
a91fa68c1d
commit
e401e87660
|
@ -29,6 +29,7 @@ requirements="\
|
||||||
ecore-input >= 1.7.0 \
|
ecore-input >= 1.7.0 \
|
||||||
ecore-imf >= 1.7.0 \
|
ecore-imf >= 1.7.0 \
|
||||||
ecore-imf-evas >= 1.7.0 \
|
ecore-imf-evas >= 1.7.0 \
|
||||||
|
ecore-ipc >= 1.7.0 \
|
||||||
efreet >= 1.7.0
|
efreet >= 1.7.0
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ about.c about.h \
|
||||||
col.c col.h \
|
col.c col.h \
|
||||||
config.c config.h \
|
config.c config.h \
|
||||||
controls.c controls.h \
|
controls.c controls.h \
|
||||||
|
ipc.c ipc.h \
|
||||||
keyin.c keyin.h \
|
keyin.c keyin.h \
|
||||||
main.c main.h \
|
main.c main.h \
|
||||||
media.c media.h \
|
media.c media.h \
|
||||||
|
|
|
@ -78,6 +78,8 @@ config_init(void)
|
||||||
(edd_base, Config, "mute", mute, EET_T_UCHAR);
|
(edd_base, Config, "mute", mute, EET_T_UCHAR);
|
||||||
EET_DATA_DESCRIPTOR_ADD_BASIC
|
EET_DATA_DESCRIPTOR_ADD_BASIC
|
||||||
(edd_base, Config, "urg_bell", urg_bell, EET_T_UCHAR);
|
(edd_base, Config, "urg_bell", urg_bell, EET_T_UCHAR);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC
|
||||||
|
(edd_base, Config, "multi_instance", multi_instance, EET_T_UCHAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -369,6 +371,7 @@ config_load(const char *key)
|
||||||
config->vidmod = 0;
|
config->vidmod = 0;
|
||||||
config->mute = EINA_FALSE;
|
config->mute = EINA_FALSE;
|
||||||
config->urg_bell = EINA_TRUE;
|
config->urg_bell = EINA_TRUE;
|
||||||
|
config->multi_instance = EINA_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct _Config
|
||||||
Eina_Bool translucent;
|
Eina_Bool translucent;
|
||||||
Eina_Bool mute;
|
Eina_Bool mute;
|
||||||
Eina_Bool urg_bell;
|
Eina_Bool urg_bell;
|
||||||
|
Eina_Bool multi_instance;
|
||||||
|
|
||||||
Eina_Bool temporary; /* not in EET */
|
Eina_Bool temporary; /* not in EET */
|
||||||
const char *config_key; /* not in EET, the key that config was loaded */
|
const char *config_key; /* not in EET, the key that config was loaded */
|
||||||
|
|
|
@ -0,0 +1,188 @@
|
||||||
|
#include "private.h"
|
||||||
|
|
||||||
|
#include <Ecore.h>
|
||||||
|
#include <Ecore_Ipc.h>
|
||||||
|
#include <Eet.h>
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
|
static Ecore_Ipc_Server *ipc = NULL;
|
||||||
|
static Ecore_Event_Handler *hnd_data = NULL;
|
||||||
|
static void (*func_new_inst) (Ipc_Instance *inst) = NULL;
|
||||||
|
static Eet_Data_Descriptor *new_inst_edd = NULL;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_ipc_cb_client_data(void *data __UNUSED__, int type __UNUSED__, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Ipc_Event_Client_Data *e = event;
|
||||||
|
|
||||||
|
if (ecore_ipc_client_server_get(e->client) != ipc)
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
if ((e->major == 3) && (e->minor == 7) && (e->data) && (e->size > 0))
|
||||||
|
{
|
||||||
|
Ipc_Instance *inst;
|
||||||
|
|
||||||
|
inst = eet_data_descriptor_decode(new_inst_edd, e->data, e->size);
|
||||||
|
if (inst)
|
||||||
|
{
|
||||||
|
if (func_new_inst) func_new_inst(inst);
|
||||||
|
// NOTE strings in inst are part of the inst alloc blob and
|
||||||
|
// dont need separate frees.
|
||||||
|
free(inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
_ipc_hash_get(void)
|
||||||
|
{
|
||||||
|
char buf[1024], hash[128];
|
||||||
|
const char *disp, *session;
|
||||||
|
char *s, i;
|
||||||
|
unsigned char c1, c2;
|
||||||
|
|
||||||
|
/* sumb stoopid hash - i'm feeling lazy */
|
||||||
|
disp = getenv("DISPLAY");
|
||||||
|
if (!disp) disp = "-unknown-";
|
||||||
|
session = getenv("DBUS_SESSION_BUS_ADDRESS");
|
||||||
|
if (!session) session = ":unknown:";
|
||||||
|
snprintf(buf, sizeof(buf), "%s/%s", disp, session);
|
||||||
|
memset(hash, 0, sizeof(hash));
|
||||||
|
memset(hash, 'x', 32);
|
||||||
|
for (i = 0, s = buf; *s; s++)
|
||||||
|
{
|
||||||
|
c1 = (((unsigned char)*s) >> 4) & 0xf;;
|
||||||
|
c2 = ((unsigned char)*s) & 0x0f;
|
||||||
|
hash[i % 32] = (((hash[i % 32] - 'a') ^ c1) % 26) + 'a';
|
||||||
|
i++;
|
||||||
|
hash[i % 32] = (((hash[i % 32] - 'a') ^ c2) % 26) + 'a';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return strdup(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_init(void)
|
||||||
|
{
|
||||||
|
Eet_Data_Descriptor_Class eddc;
|
||||||
|
|
||||||
|
ecore_ipc_init();
|
||||||
|
eet_init();
|
||||||
|
eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc),
|
||||||
|
"inst", sizeof(Ipc_Instance));
|
||||||
|
new_inst_edd = eet_data_descriptor_stream_new(&eddc);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"cmd", cmd, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"cd", cd, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"background", background, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"name", name, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"role", role, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"title", title, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"icon_name", icon_name, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"font", font, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"startup_id", startup_id, EET_T_STRING);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"x", x, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"y", y, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"w", w, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"h", h, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"pos", pos, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"login_shell", login_shell, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"fullscreen", fullscreen, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"iconic", iconic, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"borderless", borderless, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"override", override, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"maximized", maximized, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"hold", hold, EET_T_INT);
|
||||||
|
EET_DATA_DESCRIPTOR_ADD_BASIC(new_inst_edd, Ipc_Instance,
|
||||||
|
"nowm", nowm, EET_T_INT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_serve(void)
|
||||||
|
{
|
||||||
|
char *hash = _ipc_hash_get();
|
||||||
|
if (!hash) return;
|
||||||
|
ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
|
||||||
|
free(hash);
|
||||||
|
if (!ipc) return;
|
||||||
|
hnd_data = ecore_event_handler_add
|
||||||
|
(ECORE_IPC_EVENT_CLIENT_DATA, _ipc_cb_client_data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_shutdown(void)
|
||||||
|
{
|
||||||
|
if (ipc)
|
||||||
|
{
|
||||||
|
ecore_ipc_server_del(ipc);
|
||||||
|
ipc = NULL;
|
||||||
|
}
|
||||||
|
if (new_inst_edd)
|
||||||
|
{
|
||||||
|
eet_data_descriptor_free(new_inst_edd);
|
||||||
|
new_inst_edd = NULL;
|
||||||
|
}
|
||||||
|
eet_shutdown();
|
||||||
|
ecore_ipc_shutdown();
|
||||||
|
if (hnd_data)
|
||||||
|
{
|
||||||
|
ecore_event_handler_del(hnd_data);
|
||||||
|
hnd_data = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipc_instance_new_func_set(void (*func) (Ipc_Instance *inst))
|
||||||
|
{
|
||||||
|
func_new_inst = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eina_Bool
|
||||||
|
ipc_instance_add(Ipc_Instance *inst)
|
||||||
|
{
|
||||||
|
int size = 0;
|
||||||
|
void *data;
|
||||||
|
char *hash = _ipc_hash_get();
|
||||||
|
Ecore_Ipc_Server *ipcsrv;
|
||||||
|
|
||||||
|
if (!hash) return EINA_FALSE;
|
||||||
|
data = eet_data_descriptor_encode(new_inst_edd, inst, &size);
|
||||||
|
if (!data)
|
||||||
|
{
|
||||||
|
free(hash);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
ipcsrv = ecore_ipc_server_connect(ECORE_IPC_LOCAL_USER, hash, 0, NULL);
|
||||||
|
if (ipcsrv)
|
||||||
|
{
|
||||||
|
ecore_ipc_server_send(ipcsrv, 3, 7, 0, 0, 0, data, size);
|
||||||
|
ecore_ipc_server_flush(ipcsrv);
|
||||||
|
free(data);
|
||||||
|
free(hash);
|
||||||
|
ecore_ipc_server_del(ipcsrv);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
free(data);
|
||||||
|
free(hash);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef _IPC_H__
|
||||||
|
#define _IPC_H__ 1
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
typedef struct _Ipc_Instance Ipc_Instance;
|
||||||
|
|
||||||
|
struct _Ipc_Instance
|
||||||
|
{
|
||||||
|
const char *cmd;
|
||||||
|
const char *cd;
|
||||||
|
const char *background;
|
||||||
|
const char *name;
|
||||||
|
const char *role;
|
||||||
|
const char *title;
|
||||||
|
const char *icon_name;
|
||||||
|
const char *font;
|
||||||
|
const char *startup_id;
|
||||||
|
int x, y, w, h;
|
||||||
|
int pos;
|
||||||
|
int login_shell;
|
||||||
|
int fullscreen;
|
||||||
|
int iconic;
|
||||||
|
int borderless;
|
||||||
|
int override;
|
||||||
|
int maximized;
|
||||||
|
int hold;
|
||||||
|
int nowm;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ipc_init(void);
|
||||||
|
void ipc_shutdown(void);
|
||||||
|
void ipc_serve(void);
|
||||||
|
void ipc_instance_new_func_set(void (*func) (Ipc_Instance *inst));
|
||||||
|
Eina_Bool ipc_instance_add(Ipc_Instance *inst);
|
||||||
|
|
||||||
|
#endif
|
887
src/bin/main.c
887
src/bin/main.c
File diff suppressed because it is too large
Load Diff
|
@ -67,6 +67,15 @@ _cb_op_behavior_urg_bell_chg(void *data, Evas_Object *obj, void *event __UNUSED_
|
||||||
config_save(config, NULL);
|
config_save(config, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cb_op_behavior_multi_instance_chg(void *data, Evas_Object *obj, void *event __UNUSED__)
|
||||||
|
{
|
||||||
|
Evas_Object *term = data;
|
||||||
|
Config *config = termio_config_get(term);
|
||||||
|
config->multi_instance = elm_check_state_get(obj);
|
||||||
|
config_save(config, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cb_op_behavior_wsep_chg(void *data, Evas_Object *obj, void *event __UNUSED__)
|
_cb_op_behavior_wsep_chg(void *data, Evas_Object *obj, void *event __UNUSED__)
|
||||||
{
|
{
|
||||||
|
@ -187,6 +196,16 @@ options_behavior(Evas_Object *opbox, Evas_Object *term)
|
||||||
evas_object_smart_callback_add(o, "changed",
|
evas_object_smart_callback_add(o, "changed",
|
||||||
_cb_op_behavior_urg_bell_chg, term);
|
_cb_op_behavior_urg_bell_chg, term);
|
||||||
|
|
||||||
|
o = elm_check_add(bx);
|
||||||
|
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
|
||||||
|
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
|
||||||
|
elm_object_text_set(o, "Multiple instances, one process");
|
||||||
|
elm_check_state_set(o, config->multi_instance);
|
||||||
|
elm_box_pack_end(bx, o);
|
||||||
|
evas_object_show(o);
|
||||||
|
evas_object_smart_callback_add(o, "changed",
|
||||||
|
_cb_op_behavior_multi_instance_chg, term);
|
||||||
|
|
||||||
o = elm_separator_add(bx);
|
o = elm_separator_add(bx);
|
||||||
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
|
evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, 0.0);
|
||||||
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
|
evas_object_size_hint_align_set(o, EVAS_HINT_FILL, 0.5);
|
||||||
|
|
|
@ -84,8 +84,19 @@ static void
|
||||||
_cb_op_font_preview_del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event __UNUSED__)
|
_cb_op_font_preview_del(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event __UNUSED__)
|
||||||
{
|
{
|
||||||
Evas_Object *o;
|
Evas_Object *o;
|
||||||
|
Ecore_Timer *timer = evas_object_data_get(obj, "delay");
|
||||||
|
|
||||||
|
if (timer)
|
||||||
|
{
|
||||||
|
ecore_timer_del(timer);
|
||||||
|
evas_object_data_del(obj, "delay");
|
||||||
|
}
|
||||||
|
|
||||||
o = edje_object_part_swallow_get(obj, "terminology.text.preview");
|
o = edje_object_part_swallow_get(obj, "terminology.text.preview");
|
||||||
if (o) evas_object_del(o);
|
if (o)
|
||||||
|
{
|
||||||
|
evas_object_del(o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
|
|
|
@ -2310,6 +2310,7 @@ _smart_del(Evas_Object *obj)
|
||||||
|
|
||||||
_parent_sc.del(obj);
|
_parent_sc.del(obj);
|
||||||
evas_object_smart_data_set(obj, NULL);
|
evas_object_smart_data_set(obj, NULL);
|
||||||
|
free(sd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -151,7 +151,6 @@ _cb_exe_exit(void *data, int type __UNUSED__, void *event)
|
||||||
|
|
||||||
if (ev->pid != ty->pid) return ECORE_CALLBACK_PASS_ON;
|
if (ev->pid != ty->pid) return ECORE_CALLBACK_PASS_ON;
|
||||||
ty->exit_code = ev->exit_code;
|
ty->exit_code = ev->exit_code;
|
||||||
if (ty->cb.exited.func) ty->cb.exited.func(ty->cb.exited.data);
|
|
||||||
|
|
||||||
ty->pid = -1;
|
ty->pid = -1;
|
||||||
|
|
||||||
|
@ -164,6 +163,8 @@ _cb_exe_exit(void *data, int type __UNUSED__, void *event)
|
||||||
if (ty->slavefd >= 0) close(ty->slavefd);
|
if (ty->slavefd >= 0) close(ty->slavefd);
|
||||||
ty->slavefd = -1;
|
ty->slavefd = -1;
|
||||||
|
|
||||||
|
if (ty->cb.exited.func) ty->cb.exited.func(ty->cb.exited.data);
|
||||||
|
|
||||||
return ECORE_CALLBACK_PASS_ON;
|
return ECORE_CALLBACK_PASS_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,15 +323,17 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, int w, int h
|
||||||
{
|
{
|
||||||
if (i != ty->slavefd) close(i);
|
if (i != ty->slavefd) close(i);
|
||||||
}
|
}
|
||||||
ty->fd = ty->slavefd;
|
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
dup2(ty->fd, 0);
|
dup2(ty->slavefd, 0);
|
||||||
dup2(ty->fd, 1);
|
dup2(ty->slavefd, 1);
|
||||||
dup2(ty->fd, 2);
|
dup2(ty->slavefd, 2);
|
||||||
|
|
||||||
if (ioctl(ty->fd, TIOCSCTTY, NULL) < 0) exit(1);
|
|
||||||
|
|
||||||
|
if (ioctl(ty->slavefd, TIOCSCTTY, NULL) < 0) exit(1);
|
||||||
|
|
||||||
|
close(ty->fd);
|
||||||
|
close(ty->slavefd);
|
||||||
|
|
||||||
/* TODO: should we reset signals here? */
|
/* TODO: should we reset signals here? */
|
||||||
|
|
||||||
// pretend to be xterm
|
// pretend to be xterm
|
||||||
|
@ -356,6 +359,7 @@ termpty_new(const char *cmd, Eina_Bool login_shell, const char *cd, int w, int h
|
||||||
_cb_fd_read, ty,
|
_cb_fd_read, ty,
|
||||||
NULL, NULL);
|
NULL, NULL);
|
||||||
close(ty->slavefd);
|
close(ty->slavefd);
|
||||||
|
ty->slavefd = -1;
|
||||||
_pty_size(ty);
|
_pty_size(ty);
|
||||||
return ty;
|
return ty;
|
||||||
err:
|
err:
|
||||||
|
|
Loading…
Reference in New Issue