about.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /* vim: tabstop=4 shiftwidth=4 noexpandtab
  2. * This file is part of ToaruOS and is released under the terms
  3. * of the NCSA / University of Illinois License - see LICENSE.md
  4. * Copyright (C) 2018-2019 K. Lange
  5. *
  6. * about - Show an "About <Application>" dialog.
  7. *
  8. * By default, shows "About ToaruOS", suitable for use as an application
  9. * menu entry. Optionally, takes arguments specifying another application
  10. * to describe, suitable for the "Help > About" menu bar entry.
  11. */
  12. #include <toaru/yutani.h>
  13. #include <toaru/graphics.h>
  14. #include <toaru/decorations.h>
  15. #include <toaru/sdf.h>
  16. #include <toaru/menu.h>
  17. #include <sys/utsname.h>
  18. static yutani_t * yctx;
  19. static yutani_window_t * window = NULL;
  20. static gfx_context_t * ctx = NULL;
  21. static sprite_t logo;
  22. static int32_t width = 350;
  23. static int32_t height = 250;
  24. static char * version_str;
  25. static char * icon_path;
  26. static char * title_str;
  27. static char * version_str;
  28. static char * copyright_str[20] = {NULL};
  29. static int center_x(int x) {
  30. return (width - x) / 2;
  31. }
  32. static void draw_string(int y, const char * string, int font, uint32_t color) {
  33. struct decor_bounds bounds;
  34. decor_get_bounds(window, &bounds);
  35. draw_sdf_string(ctx, bounds.left_width + center_x(draw_sdf_string_width(string, 16, font)), bounds.top_height + 10 + logo.height + 10 + y, string, 16, color, font);
  36. }
  37. static void redraw(void) {
  38. struct decor_bounds bounds;
  39. decor_get_bounds(window, &bounds);
  40. draw_fill(ctx, rgb(204,204,204));
  41. draw_sprite(ctx, &logo, bounds.left_width + center_x(logo.width), bounds.top_height + 10);
  42. draw_string(0, version_str, SDF_FONT_BOLD, rgb(0,0,0));
  43. int offset = 20;
  44. for (char ** copy_str = copyright_str; *copy_str; ++copy_str) {
  45. if (**copy_str == '-') {
  46. offset += 10;
  47. } else if (**copy_str == '%') {
  48. draw_string(offset, *copy_str+1, SDF_FONT_THIN, rgb(0,0,255));
  49. offset += 20;
  50. } else {
  51. draw_string(offset, *copy_str, SDF_FONT_THIN, rgb(0,0,0));
  52. offset += 20;
  53. }
  54. }
  55. window->decorator_flags |= DECOR_FLAG_NO_MAXIMIZE;
  56. render_decorations(window, ctx, title_str);
  57. flip(ctx);
  58. yutani_flip(yctx, window);
  59. }
  60. static void init_default(void) {
  61. title_str = "About ToaruOS";
  62. icon_path = "/usr/share/logo_login.bmp";
  63. {
  64. version_str = malloc(100);
  65. struct utsname u;
  66. uname(&u);
  67. char * tmp = strstr(u.release, "-");
  68. if (tmp) {
  69. *tmp = '\0';
  70. }
  71. sprintf(version_str, "ToaruOS %s", u.release);
  72. }
  73. copyright_str[0] = "(C) 2011-2019 K. Lange, et al.";
  74. copyright_str[1] = "-";
  75. copyright_str[2] = "ToaruOS is free software released under the";
  76. copyright_str[3] = "NCSA/University of Illinois license.";
  77. copyright_str[4] = "-";
  78. copyright_str[5] = "%https://toaruos.org";
  79. copyright_str[6] = "%https://github.com/klange/toaruos";
  80. }
  81. int main(int argc, char * argv[]) {
  82. int req_center_x, req_center_y;
  83. yctx = yutani_init();
  84. if (!yctx) {
  85. fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
  86. return 1;
  87. }
  88. init_decorations();
  89. struct decor_bounds bounds;
  90. decor_get_bounds(NULL, &bounds);
  91. window = yutani_window_create_flags(yctx, width + bounds.width, height + bounds.height, YUTANI_WINDOW_FLAG_DIALOG_ANIMATION);
  92. req_center_x = yctx->display_width / 2;
  93. req_center_y = yctx->display_height / 2;
  94. if (argc < 2) {
  95. init_default();
  96. } else if (argc < 5) {
  97. fprintf(stderr, "Invalid arguments.\n");
  98. return 1;
  99. } else {
  100. title_str = argv[1];
  101. icon_path = argv[2];
  102. version_str = argv[3];
  103. int i = 0;
  104. char * me = argv[4], * end;
  105. do {
  106. copyright_str[i] = me;
  107. i++;
  108. end = strchr(me,'\n');
  109. if (end) {
  110. *end = '\0';
  111. me = end+1;
  112. }
  113. } while (end);
  114. if (argc > 6) {
  115. req_center_x = atoi(argv[5]);
  116. req_center_y = atoi(argv[6]);
  117. }
  118. }
  119. yutani_window_move(yctx, window, req_center_x - window->width / 2, req_center_y - window->height / 2);
  120. yutani_window_advertise_icon(yctx, window, title_str, "star");
  121. ctx = init_graphics_yutani_double_buffer(window);
  122. load_sprite(&logo, icon_path);
  123. logo.alpha = ALPHA_EMBEDDED;
  124. redraw();
  125. int playing = 1;
  126. while (playing) {
  127. yutani_msg_t * m = yutani_poll(yctx);
  128. while (m) {
  129. if (menu_process_event(yctx, m)) {
  130. redraw();
  131. }
  132. switch (m->type) {
  133. case YUTANI_MSG_KEY_EVENT:
  134. {
  135. struct yutani_msg_key_event * ke = (void*)m->data;
  136. if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
  137. playing = 0;
  138. }
  139. }
  140. break;
  141. case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
  142. {
  143. struct yutani_msg_window_focus_change * wf = (void*)m->data;
  144. yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
  145. if (win) {
  146. win->focused = wf->focused;
  147. redraw();
  148. }
  149. }
  150. break;
  151. #if 0
  152. case YUTANI_MSG_RESIZE_OFFER:
  153. {
  154. struct yutani_msg_window_resize * wr = (void*)m->data;
  155. resize_finish(wr->width, wr->height);
  156. }
  157. break;
  158. #endif
  159. case YUTANI_MSG_WINDOW_MOUSE_EVENT:
  160. {
  161. struct yutani_msg_window_mouse_event * me = (void*)m->data;
  162. int result = decor_handle_event(yctx, m);
  163. switch (result) {
  164. case DECOR_CLOSE:
  165. playing = 0;
  166. break;
  167. case DECOR_RIGHT:
  168. /* right click in decoration, show appropriate menu */
  169. decor_show_default_menu(window, window->x + me->new_x, window->y + me->new_y);
  170. break;
  171. default:
  172. /* Other actions */
  173. break;
  174. }
  175. }
  176. break;
  177. case YUTANI_MSG_WINDOW_CLOSE:
  178. case YUTANI_MSG_SESSION_END:
  179. playing = 0;
  180. break;
  181. default:
  182. break;
  183. }
  184. free(m);
  185. m = yutani_poll_async(yctx);
  186. }
  187. }
  188. yutani_close(yctx, window);
  189. return 0;
  190. }