1 #define E_COMP_WL
2 #include "e.h"
3 #include "e_mod_main.h"
4 
5 EINTERN Eina_Hash *shell_resources;
6 EINTERN Eina_Hash *xdg_shell_resources;
7 EINTERN Eina_List *hooks;
8 
9 EINTERN void
e_shell_surface_destroy(struct wl_resource * resource)10 e_shell_surface_destroy(struct wl_resource *resource)
11 {
12    E_Client *ec;
13    E_Shell_Data *shd;
14 
15    /* DBG("Shell Surface Destroy: %d", wl_resource_get_id(resource)); */
16 
17    /* get the client for this resource */
18    ec = wl_resource_get_user_data(resource);
19    if (!ec) return;
20    wl_resource_set_user_data(resource, NULL);
21    /* client may be passed here during DEL hook */
22    if (!ec->comp_data) return;
23 
24    if (ec->comp_data->grab)
25      {
26         e_comp_wl_grab_client_del(ec, 0);
27         ec->comp_data->grab = 0;
28      }
29 
30 
31    if (resource == ec->comp_data->shell.surface)
32      ec->comp_data->shell.surface = NULL;
33    shd = ec->comp_data->shell.data;
34    if (shd)
35      {
36         E_FREE_LIST(shd->pending, free);
37         if ((resource == shd->surface) || (!shd->surface))
38           E_FREE(ec->comp_data->shell.data);
39      }
40 
41    if (ec->comp_data->mapped)
42      {
43         if ((ec->comp_data->shell.surface) &&
44             (ec->comp_data->shell.unmap))
45           ec->comp_data->shell.unmap(ec->comp_data->shell.surface);
46      }
47    if (ec->parent)
48      {
49         ec->parent->transients =
50           eina_list_remove(ec->parent->transients, ec);
51      }
52 
53    e_object_unref(E_OBJECT(ec));
54 }
55 
56 EINTERN void
e_shell_surface_cb_destroy(struct wl_resource * resource)57 e_shell_surface_cb_destroy(struct wl_resource *resource)
58 {
59    /* DBG("Shell Surface Destroy: %d", wl_resource_get_id(resource)); */
60 
61    e_shell_surface_destroy(resource);
62 }
63 
64 EINTERN void
e_shell_surface_parent_set(E_Client * ec,struct wl_resource * parent_resource)65 e_shell_surface_parent_set(E_Client *ec, struct wl_resource *parent_resource)
66 {
67    E_Client *pc;
68    uint64_t pwin = 0;
69 
70    if (!parent_resource)
71      {
72         ec->icccm.fetch.transient_for = EINA_FALSE;
73         ec->icccm.transient_for = 0;
74         if (ec->parent)
75           {
76              ec->parent->transients =
77                 eina_list_remove(ec->parent->transients, ec);
78              if (ec->parent->modal == ec) ec->parent->modal = NULL;
79              ec->parent = NULL;
80           }
81         return;
82      }
83 
84    pc = wl_resource_get_user_data(parent_resource);
85    if (!pc)
86      {
87         ERR("Could not get parent resource client");
88         return;
89      }
90 
91    pwin = e_pixmap_window_get(pc->pixmap);
92 
93    e_pixmap_parent_window_set(ec->pixmap, pwin);
94    e_client_parent_set(ec, pc);
95 
96    ec->icccm.fetch.transient_for = EINA_TRUE;
97    ec->icccm.transient_for = pwin;
98 }
99 
100 EINTERN void
e_shell_surface_mouse_down_helper(E_Client * ec,E_Binding_Event_Mouse_Button * ev,Eina_Bool move)101 e_shell_surface_mouse_down_helper(E_Client *ec, E_Binding_Event_Mouse_Button *ev, Eina_Bool move)
102 {
103    if (move)
104      {
105         /* tell E to start moving the client */
106         e_client_act_move_begin(ec, ev);
107 
108         /* we have to get a reference to the window_move action here, or else
109          * when e_client stops the move we will never get notified */
110         ec->cur_mouse_action = e_action_find("window_move");
111         if (ec->cur_mouse_action)
112           e_object_ref(E_OBJECT(ec->cur_mouse_action));
113      }
114    else
115      {
116         /* tell E to start resizing the client */
117         e_client_act_resize_begin(ec, ev);
118 
119         /* we have to get a reference to the window_resize action here,
120          * or else when e_client stops the resize we will never get notified */
121         ec->cur_mouse_action = e_action_find("window_resize");
122         if (ec->cur_mouse_action)
123           e_object_ref(E_OBJECT(ec->cur_mouse_action));
124      }
125 
126    e_focus_event_mouse_down(ec);
127 }
128 
129 EINTERN E_Shell_Data *
e_shell_data_new(unsigned int version)130 e_shell_data_new(unsigned int version)
131 {
132    E_Shell_Data *shd;
133 
134    shd = E_NEW(E_Shell_Data, 1);
135    shd->version = version;
136    return shd;
137 }
138 
139 static Eina_Bool
desktop_xwayland_startup()140 desktop_xwayland_startup()
141 {
142    e_startup();
143    return ECORE_CALLBACK_RENEW;
144 }
145 
146 static void
desktop_startup()147 desktop_startup()
148 {
149    if (e_module_find("xwayland"))
150      ecore_event_handler_add(E_EVENT_COMPOSITOR_XWAYLAND_INIT, desktop_xwayland_startup, NULL);
151    else
152      e_startup();
153 }
154 
155 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Wl_Desktop_Shell" };
156 
157 E_API void *
e_modapi_init(E_Module * m)158 e_modapi_init(E_Module *m)
159 {
160    Eina_Bool have_shell;
161 
162    /* try to create global shell interface */
163    if (!wl_global_create(e_comp_wl->wl.disp, &wl_shell_interface, 1,
164                          NULL, wl_shell_cb_bind))
165      {
166         ERR("Could not create shell global");
167         return NULL;
168      }
169 
170    have_shell = e_xdg_shell_v6_init() | e_xdg_shell_init();
171    if (!have_shell) return NULL;
172 
173 #ifdef HAVE_WL_TEXT_INPUT
174    if (!e_input_panel_init())
175      {
176         ERR("Could not init input panel");
177         return NULL;
178      }
179 #endif
180    ecore_job_add(desktop_startup, NULL);
181 
182    shell_resources = eina_hash_pointer_new(NULL);
183    xdg_shell_resources = eina_hash_pointer_new(NULL);
184 
185    return m;
186 }
187 
188 E_API int
e_modapi_shutdown(E_Module * m EINA_UNUSED)189 e_modapi_shutdown(E_Module *m EINA_UNUSED)
190 {
191    e_input_panel_shutdown();
192    eina_hash_free(shell_resources);
193    eina_hash_free(xdg_shell_resources);
194    E_FREE_LIST(hooks, e_client_hook_del);
195    return 1;
196 }
197