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