337 lines
8.8 KiB
C
337 lines
8.8 KiB
C
#define E_COMP_WL
|
|
#include "e.h"
|
|
#include "e_mod_main.h"
|
|
#include "input-method-unstable-v1-server-protocol.h"
|
|
|
|
typedef struct _E_Input_Panel E_Input_Panel;
|
|
typedef struct _E_Input_Panel_Surface E_Input_Panel_Surface;
|
|
|
|
struct _E_Input_Panel
|
|
{
|
|
struct wl_resource *resource;
|
|
Eina_List *surfaces;
|
|
};
|
|
|
|
struct _E_Input_Panel_Surface
|
|
{
|
|
E_Client *ec;
|
|
|
|
Eina_Bool panel;
|
|
Eina_Bool showing;
|
|
};
|
|
|
|
static E_Input_Panel input_panel;
|
|
static Eina_List *handlers = NULL;
|
|
static struct wl_global *input_panel_global = NULL;
|
|
|
|
static void
|
|
_e_input_panel_surface_cb_toplevel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *output_resource EINA_UNUSED, uint32_t position EINA_UNUSED)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
ips->panel = EINA_FALSE;
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_surface_cb_overlay_panel_set(struct wl_client *client EINA_UNUSED, struct wl_resource *resource)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
ips->panel = EINA_TRUE;
|
|
}
|
|
|
|
static const struct zwp_input_panel_surface_v1_interface _e_input_panel_surface_implementation = {
|
|
_e_input_panel_surface_cb_toplevel_set,
|
|
_e_input_panel_surface_cb_overlay_panel_set
|
|
};
|
|
|
|
static void
|
|
_e_input_panel_surface_resource_destroy(struct wl_resource *resource)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
E_Client *ec;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
ec = ips->ec;
|
|
if (!e_object_is_del(E_OBJECT(ec)))
|
|
{
|
|
if (ec->comp_data->mapped)
|
|
{
|
|
if ((ec->comp_data->shell.surface) &&
|
|
(ec->comp_data->shell.unmap))
|
|
ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
|
|
}
|
|
if (ec->parent)
|
|
{
|
|
ec->parent->transients =
|
|
eina_list_remove(ec->parent->transients, ec);
|
|
}
|
|
ec->comp_data->shell.surface = NULL;
|
|
}
|
|
|
|
input_panel.surfaces = eina_list_remove(input_panel.surfaces, ips);
|
|
|
|
free(ips);
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_position_set(E_Client *ec, int w, int h)
|
|
{
|
|
int nx, ny;
|
|
int zx, zy, zw, zh;
|
|
|
|
e_zone_useful_geometry_get(ec->zone, &zx, &zy, &zw, &zh);
|
|
|
|
nx = zx + (zw - w) / 2;
|
|
ny = zy + zh - h;
|
|
|
|
e_client_util_move_without_frame(ec, nx, ny);
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_surface_visible_update(E_Input_Panel_Surface *ips)
|
|
{
|
|
E_Client *ec;
|
|
|
|
ec = ips->ec;
|
|
if ((ips->showing) &&
|
|
(e_pixmap_usable_get(ec->pixmap)))
|
|
{
|
|
if (!ips->panel)
|
|
_e_input_panel_position_set(ec, ec->client.w, ec->client.h);
|
|
|
|
ec->visible = EINA_TRUE;
|
|
evas_object_geometry_set(ec->frame, ec->x, ec->y, ec->w, ec->h);
|
|
evas_object_show(ec->frame);
|
|
e_comp_object_damage(ec->frame, ec->x, ec->y, ec->w, ec->h);
|
|
}
|
|
else
|
|
{
|
|
ec->visible = EINA_FALSE;
|
|
evas_object_hide(ec->frame);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_surface_configure(struct wl_resource *resource, Evas_Coord x EINA_UNUSED, Evas_Coord y EINA_UNUSED, Evas_Coord w, Evas_Coord h)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
|
|
e_client_util_resize_without_frame(ips->ec, w, h);
|
|
|
|
if (ips->showing)
|
|
_e_input_panel_surface_visible_update(ips);
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_surface_map(struct wl_resource *resource)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
E_Client *ec;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
ec = ips->ec;
|
|
|
|
if (e_object_is_del(E_OBJECT(ec)))
|
|
return;
|
|
|
|
// NOTE: we need to set mapped, so that avoid showing evas_object and continue buffer's commit process.
|
|
if ((!ec->comp_data->mapped) && (e_pixmap_usable_get(ec->pixmap)))
|
|
ec->comp_data->mapped = EINA_TRUE;
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_surface_unmap(struct wl_resource *resource)
|
|
{
|
|
E_Input_Panel_Surface *ips;
|
|
E_Client *ec;
|
|
|
|
ips = wl_resource_get_user_data(resource);
|
|
ec = ips->ec;
|
|
|
|
if (e_object_is_del(E_OBJECT(ec)))
|
|
return;
|
|
|
|
if (ec->comp_data->mapped)
|
|
{
|
|
ec->visible = EINA_FALSE;
|
|
evas_object_hide(ec->frame);
|
|
ec->comp_data->mapped = EINA_FALSE;
|
|
}
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_cb_surface_get(struct wl_client *client, struct wl_resource *resource EINA_UNUSED, uint32_t id, struct wl_resource *surface_resource)
|
|
{
|
|
E_Client *ec;
|
|
E_Input_Panel_Surface *ips;
|
|
E_Comp_Client_Data *cd;
|
|
|
|
ec = wl_resource_get_user_data(surface_resource);
|
|
if (!ec)
|
|
{
|
|
wl_resource_post_error(surface_resource,
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
"No Client Set On Surface");
|
|
return;
|
|
}
|
|
|
|
cd = ec->comp_data;
|
|
if (!cd)
|
|
{
|
|
wl_resource_post_error(surface_resource,
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
"No Comp Data For Client");
|
|
return;
|
|
}
|
|
|
|
/* check for existing shell surface */
|
|
if (ec->comp_data->shell.surface)
|
|
{
|
|
wl_resource_post_error(surface_resource,
|
|
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
"Client already has shell surface");
|
|
return;
|
|
}
|
|
|
|
ips = E_NEW(E_Input_Panel_Surface, 1);
|
|
if (!ips)
|
|
{
|
|
wl_client_post_no_memory(client);
|
|
return;
|
|
}
|
|
|
|
cd->shell.surface = wl_resource_create(client,
|
|
&zwp_input_panel_surface_v1_interface,
|
|
1, id);
|
|
if (!cd->shell.surface)
|
|
{
|
|
wl_client_post_no_memory(client);
|
|
free(ips);
|
|
return;
|
|
}
|
|
|
|
ips->ec = ec;
|
|
|
|
EC_CHANGED(ec);
|
|
if (!ec->new_client)
|
|
{
|
|
ec->new_client = EINA_TRUE;
|
|
e_comp->new_clients++;
|
|
}
|
|
if (ec->ignored)
|
|
e_client_unignore(ec);
|
|
|
|
/* set input panel client properties */
|
|
ec->borderless = EINA_TRUE;
|
|
ec->argb = EINA_TRUE;
|
|
ec->lock_border = EINA_TRUE;
|
|
ec->lock_focus_in = ec->lock_focus_out = EINA_TRUE;
|
|
ec->netwm.state.skip_taskbar = EINA_TRUE;
|
|
ec->netwm.state.skip_pager = EINA_TRUE;
|
|
ec->no_shape_cut = EINA_TRUE;
|
|
ec->border_size = 0;
|
|
ec->netwm.type = E_WINDOW_TYPE_UTILITY;
|
|
ec->comp_data->set_win_type = EINA_TRUE;
|
|
|
|
|
|
cd->surface = surface_resource;
|
|
cd->shell.configure_send = NULL;
|
|
cd->shell.configure = _e_input_panel_surface_configure;
|
|
cd->shell.ping = NULL;
|
|
cd->shell.map = _e_input_panel_surface_map;
|
|
cd->shell.unmap = _e_input_panel_surface_unmap;
|
|
|
|
|
|
wl_resource_set_implementation(cd->shell.surface,
|
|
&_e_input_panel_surface_implementation,
|
|
ips, _e_input_panel_surface_resource_destroy);
|
|
|
|
input_panel.surfaces = eina_list_append(input_panel.surfaces, ips);
|
|
}
|
|
|
|
static const struct zwp_input_panel_v1_interface _e_input_panel_implementation = {
|
|
_e_input_panel_cb_surface_get
|
|
};
|
|
|
|
static void
|
|
_e_input_panel_unbind(struct wl_resource *resource EINA_UNUSED)
|
|
{
|
|
input_panel.resource = NULL;
|
|
|
|
E_FREE_FUNC(input_panel.surfaces, eina_list_free);
|
|
}
|
|
|
|
static void
|
|
_e_input_panel_bind(struct wl_client *client, void *data EINA_UNUSED, uint32_t version EINA_UNUSED, uint32_t id)
|
|
{
|
|
struct wl_resource *resource;
|
|
|
|
resource = wl_resource_create(client, &zwp_input_panel_v1_interface, 1, id);
|
|
if (!resource)
|
|
{
|
|
wl_client_post_no_memory(client);
|
|
return;
|
|
}
|
|
|
|
if (input_panel.resource)
|
|
{
|
|
wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
|
|
"interface object already bound");
|
|
return;
|
|
}
|
|
|
|
input_panel.resource = resource;
|
|
|
|
wl_resource_set_implementation(resource,
|
|
&_e_input_panel_implementation,
|
|
NULL, _e_input_panel_unbind);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_e_input_panel_cb_visible_change(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
|
{
|
|
E_Event_Text_Input_Panel_Visibility_Change *ev = event;
|
|
E_Input_Panel_Surface *ips;
|
|
Eina_List *l;
|
|
|
|
EINA_LIST_FOREACH(input_panel.surfaces, l, ips)
|
|
{
|
|
if (!ips->ec) continue;
|
|
ips->showing = ev->visible;
|
|
_e_input_panel_surface_visible_update(ips);
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
EINTERN Eina_Bool
|
|
e_input_panel_init(void)
|
|
{
|
|
E_LIST_HANDLER_APPEND(handlers, E_EVENT_TEXT_INPUT_PANEL_VISIBILITY_CHANGE,
|
|
_e_input_panel_cb_visible_change, NULL);
|
|
// TODO: add signal handler - update input panel
|
|
|
|
input_panel_global = wl_global_create(e_comp->wl_comp_data->wl.disp,
|
|
&zwp_input_panel_v1_interface, 1,
|
|
NULL, _e_input_panel_bind);
|
|
if (!input_panel_global)
|
|
{
|
|
ERR("failed to create wl_global for input panel");
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
EINTERN void
|
|
e_input_panel_shutdown(void)
|
|
{
|
|
E_FREE_FUNC(input_panel_global, wl_global_destroy);
|
|
E_FREE_LIST(handlers, ecore_event_handler_del);
|
|
}
|