1 #include "config.h"
2 
3 //# include "e_drm2.x"
4 
5 #include <Elementary.h>
6 #ifndef HAVE_WAYLAND_ONLY
7 # include <Ecore_X.h>
8 #endif
9 
10 static int         ret = 0, sig = 0, exit_gdb = 0;
11 static pid_t       pid;
12 static Eina_Bool   tainted = EINA_FALSE;
13 static const char *backtrace_str = NULL;
14 
15 //#define FONT           "TopazPlus_a500_v1.0.pcf"
16 //#define FONT           "terminus-16.pcf"
17 #define FONT           "Topaz_a500_v1.0.ttf"
18 #define FONT_FALLBACK  "Mono"
19 #define COL_BG         0,   0,   0, 255
20 #define COL_FG         255,   0,   0, 255
21 #define HDIV           10
22 #define PDIV           20
23 #define BLINK          0.8
24 #define RECOVER_BUTTON 1
25 #define RECOVER_KEY    "F1"
26 #define ABORT_BUTTON   3
27 #define ABORT_KEY      "F12"
28 
title1(void)29 static inline const char *title1(void) {
30    return "Software Failure. Press left mouse button / F1 to recover, right mouse button / F12 to abort.";
31 }
title2(void)32 static inline const char *title2(void) { static char buf[512];
33    if (tainted) snprintf
34      (buf, sizeof(buf), "Tainted by unsupported modules");
35    else if (exit_gdb) snprintf
36      (buf, sizeof(buf), "Couldn't run gdb to collect a backtrace");
37    else if (backtrace_str) snprintf
38      (buf, sizeof(buf), "Backtrace log: %s", backtrace_str);
39    else snprintf
40      (buf, sizeof(buf), " ");
41    return buf;
42 }
title3(void)43 static inline const char *title3(void) { static char buf[512];
44    snprintf(buf, sizeof(buf), "Guru Meditation #%08d.%08d", pid, sig);
45    return buf;
46 }
47 
48 /////////////////////////////////////////////////////////////////////////////
49 
50 static Evas_Object *obj_base = NULL;
51 static Evas_Object *obj_outer = NULL;
52 static Evas_Object *obj_inner = NULL;
53 static Evas_Object *obj_line1 = NULL;
54 static Evas_Object *obj_line2 = NULL;
55 static Evas_Object *obj_line3 = NULL;
56 
57 static void
mouse_up(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * o EINA_UNUSED,void * info)58 mouse_up(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *info)
59 {
60    Evas_Event_Mouse_Up *ev = info;
61 
62    if (ev->button == RECOVER_BUTTON)
63      {
64         ret = 2;
65         elm_exit();
66      }
67    else if (ev->button == ABORT_BUTTON)
68      {
69         ret = 1;
70         elm_exit();
71      }
72 }
73 
74 static void
key_down(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * o EINA_UNUSED,void * info)75 key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *o EINA_UNUSED, void *info)
76 {
77    Evas_Event_Key_Down *ev = info;
78 
79    if (!strcmp(ev->key, RECOVER_KEY))
80      {
81         ret = 2;
82         elm_exit();
83      }
84    else if (!strcmp(ev->key, ABORT_KEY))
85      {
86         ret = 1;
87         elm_exit();
88      }
89 }
90 
91 static const char *
font_get(void)92 font_get(void)
93 {
94    const char *s = getenv("E_ALERT_FONT_DIR");
95    static char buf[4096];
96 
97    if (s) snprintf(buf, sizeof(buf), "%s/"FONT, s);
98    else snprintf(buf, sizeof(buf), "%s", FONT_FALLBACK);
99    return buf;
100 }
101 
102 static void
resize(void * data EINA_UNUSED,Evas * e EINA_UNUSED,Evas_Object * o,void * info EINA_UNUSED)103 resize(void *data EINA_UNUSED, Evas *e EINA_UNUSED, Evas_Object *o, void *info EINA_UNUSED)
104 {
105    Evas_Coord w, h, tw, th;
106    const char *font = font_get();
107 
108    evas_object_geometry_get(o, NULL, NULL, &w, &h);
109    h = w / HDIV;
110 
111    evas_object_geometry_set(obj_base, 0, 0, w, h * HDIV * 2);
112    evas_object_geometry_set(obj_outer, (1 * h) / PDIV, (1 * h) / PDIV,
113                             w - ((h * 2) / PDIV), h - ((h * 2) / PDIV));
114    evas_object_geometry_set(obj_inner, (2 * h) / PDIV, (2 * h) / PDIV,
115                             w - ((h * 4) / PDIV), h - ((h * 4) / PDIV));
116 
117    evas_object_text_font_set(obj_line1, font, h / 8);
118    evas_object_geometry_get(obj_line1, NULL, NULL, &tw, &th);
119    evas_object_move(obj_line1, (w - tw) / 2, (3 * h) / PDIV);
120 
121    evas_object_text_font_set(obj_line2, font, h / 8);
122    evas_object_geometry_get(obj_line2, NULL, NULL, &tw, &th);
123    evas_object_move(obj_line2, (w - tw) / 2, (h - th) / 2);
124 
125    evas_object_text_font_set(obj_line3, font, h / 8);
126    evas_object_geometry_get(obj_line3, NULL, NULL, &tw, &th);
127    evas_object_move(obj_line3, (w - tw) / 2, h - th - (3 * h) / PDIV);
128 }
129 
130 static Eina_Bool
timer(void * data EINA_UNUSED)131 timer(void *data EINA_UNUSED)
132 {
133    if (evas_object_visible_get(obj_outer)) evas_object_hide(obj_outer);
134    else evas_object_show(obj_outer);
135    return EINA_TRUE;
136 }
137 
138 static Eina_Bool
setup_display(void)139 setup_display(void)
140 {
141    Evas *e;
142    Evas_Object *win, *o;
143    const char *font = font_get();
144 
145    win = o = elm_win_add(NULL, "e-alert", ELM_WIN_SPLASH);
146    if (!win) return EINA_FALSE;
147    e = evas_object_evas_get(win);
148    elm_win_override_set(o, EINA_TRUE);
149 
150    obj_base = o = evas_object_rectangle_add(e);
151    evas_object_color_set(o, COL_BG);
152    evas_object_show(o);
153 
154    obj_outer = o = evas_object_rectangle_add(e);
155    evas_object_color_set(o, COL_FG);
156    evas_object_pass_events_set(o, EINA_TRUE);
157    evas_object_show(o);
158 
159    obj_inner = o = evas_object_rectangle_add(e);
160    evas_object_color_set(o, COL_BG);
161    evas_object_pass_events_set(o, EINA_TRUE);
162    evas_object_show(o);
163 
164    obj_line1 = o = evas_object_text_add(e);
165    evas_object_color_set(o, COL_FG);
166    evas_object_text_font_set(o, font, 10);
167    evas_object_text_text_set(o, title1());
168    evas_object_pass_events_set(o, EINA_TRUE);
169    evas_object_show(o);
170 
171    obj_line2 = o = evas_object_text_add(e);
172    evas_object_color_set(o, COL_FG);
173    evas_object_text_font_set(o, font, 10);
174    evas_object_text_text_set(o, title2());
175    evas_object_pass_events_set(o, EINA_TRUE);
176    evas_object_show(o);
177 
178    obj_line3 = o = evas_object_text_add(e);
179    evas_object_color_set(o, COL_FG);
180    evas_object_text_font_set(o, font, 10);
181    evas_object_text_text_set(o, title3());
182    evas_object_pass_events_set(o, EINA_TRUE);
183    evas_object_show(o);
184 
185    evas_object_event_callback_add(obj_base, EVAS_CALLBACK_MOUSE_UP, mouse_up, NULL);
186    evas_object_event_callback_add(win, EVAS_CALLBACK_KEY_DOWN, key_down, NULL);
187    evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, resize, NULL);
188 
189    ecore_timer_add(BLINK, timer, NULL);
190 
191    resize(NULL, e, win, NULL);
192 
193 #ifndef HAVE_WAYLAND_ONLY
194    if (getenv("DISPLAY"))
195      {
196         Ecore_X_Window root = ecore_x_window_root_first_get();
197         Ecore_X_Atom atom_composite_win = ecore_x_atom_get("_E_COMP_WINDOW");
198         unsigned int id;
199         if (ecore_x_window_prop_card32_get(root, atom_composite_win, &id, 1) > 0)
200           {
201              Ecore_X_Window elmwin = elm_win_xwindow_get(win);
202              ecore_x_window_reparent(elmwin, id, 0, 0);
203              Ecore_X_Randr_Output output = ecore_x_randr_primary_output_get(root);
204              Ecore_X_Randr_Crtc crct = ecore_x_randr_output_crtc_get(root, output);
205              int x = 0, y = 0, w = 1, h = 1;
206              ecore_x_randr_crtc_geometry_get(root, crct, &x, &y, &w, &h);
207              ecore_x_window_move_resize(elmwin, x, y, w, w / HDIV);
208           }
209      }
210 #endif
211 
212    evas_object_show(win);
213 
214 #ifndef HAVE_WAYLAND_ONLY
215    if (getenv("DISPLAY"))
216      {
217         Ecore_X_Window elmwin = elm_win_xwindow_get(win);
218         ecore_x_pointer_grab(elmwin);
219         ecore_x_keyboard_grab(elmwin);
220      }
221 #endif
222    return EINA_TRUE;
223 }
224 
225 int
main(int argc,char ** argv)226 main(int argc, char **argv)
227 {
228    const char *s;
229    int i = 0;
230 
231    for (i = 1; i < argc; i++)
232      {
233         if ((!strcmp(argv[i], "-h")) ||
234             (!strcmp(argv[i], "-help")) ||
235             (!strcmp(argv[i], "--help")))
236           {
237              printf("This is an internal tool for Enlightenment.\n"
238                     "do not use it.\n");
239              exit(0);
240           }
241         else if (i == 1) sig           = atoi(argv[i]);  // signal
242         else if (i == 2) pid           = atoi(argv[i]);  // E's pid
243         else if (i == 3) exit_gdb      = atoi(argv[i]);
244         else if (i == 4) backtrace_str = argv[i];
245      }
246    fprintf(stderr, "exit_gdb: %i\n", exit_gdb);
247 
248    s = getenv("E_TAINTED");
249    if      (s && !strcmp(s, "NO")) tainted = EINA_FALSE;
250    else if (s && !strcmp(s, "YES")) tainted = EINA_TRUE;
251 
252    ecore_app_no_system_modules();
253    elm_init(argc, argv);
254 
255    if (setup_display())
256      {
257         s = getenv("E_ALERT_SYSTEM_BIN");
258         if (s && s[0])
259           {
260              putenv("E_ALERT_BACKLIGHT_RESET=1");
261              ecore_exe_pipe_run
262                (s, ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_WRITE |
263                 ECORE_EXE_NOT_LEADER | ECORE_EXE_TERM_WITH_PARENT, NULL);
264           }
265 
266         elm_run();
267      }
268 
269    return ret;
270 }
271