imgviewer.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 K. Lange
  5. *
  6. * imgviewer - Display bitmaps in a graphical window.
  7. *
  8. * This is probably the 4th time I've (re)written a version of
  9. * this application... This uses the libtoaru_graphics sprite
  10. * functionality to load images, so it will support whatever
  11. * that ends up supporting - which at the time of writing is
  12. * just bitmaps of various types.
  13. *
  14. */
  15. #include <stdio.h>
  16. #include <stdint.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <time.h>
  20. #include <unistd.h>
  21. #include <getopt.h>
  22. #include <toaru/yutani.h>
  23. #include <toaru/graphics.h>
  24. #include <toaru/decorations.h>
  25. #include <toaru/menu.h>
  26. /* Pointer to graphics memory */
  27. static yutani_t * yctx;
  28. static yutani_window_t * window = NULL;
  29. static gfx_context_t * ctx = NULL;
  30. static int decor_left_width = 0;
  31. static int decor_top_height = 0;
  32. static int decor_right_width = 0;
  33. static int decor_bottom_height = 0;
  34. static int decor_width = 0;
  35. static int decor_height = 0;
  36. int left = 40;
  37. int top = 40;
  38. int width = 300;
  39. int height = 300;
  40. sprite_t img = {0};
  41. #define APPLICATION_TITLE "Image Viewer"
  42. void usage(char * argv[]) {
  43. printf(
  44. "Image Viewer - Shows images.\n"
  45. "\n"
  46. "usage: %s \033[3mimage\033[0m\n"
  47. "\n"
  48. " -? --help \033[3mShow this help message.\033[0m\n",
  49. argv[0]);
  50. }
  51. static void decors() {
  52. render_decorations(window, ctx, APPLICATION_TITLE);
  53. }
  54. void redraw() {
  55. static double r = 0.0;
  56. for (int y = 0; y < height; ++y) {
  57. for (int x = 0; x < width; ++x) {
  58. GFX(ctx,x+decor_left_width,y+decor_top_height) = (((y / 10) % 2 == 0) ^ ((x / 10) % 2 == 0)) ? rgb(107,107,107) : rgb(147,147,147);
  59. }
  60. }
  61. draw_sprite(ctx, &img, decor_left_width + width/2 - img.width/2, decor_top_height + height/2 - img.height/2);
  62. decors();
  63. flip(ctx);
  64. r += 0.02;
  65. }
  66. void resize_finish(int w, int h) {
  67. yutani_window_resize_accept(yctx, window, w, h);
  68. reinit_graphics_yutani(ctx, window);
  69. struct decor_bounds bounds;
  70. decor_get_bounds(window, &bounds);
  71. decor_left_width = bounds.left_width;
  72. decor_top_height = bounds.top_height;
  73. decor_right_width = bounds.right_width;
  74. decor_bottom_height = bounds.bottom_height;
  75. decor_width = bounds.width;
  76. decor_height = bounds.height;
  77. width = w - decor_left_width - decor_right_width;
  78. height = h - decor_top_height - decor_bottom_height;
  79. redraw();
  80. yutani_window_resize_done(yctx, window);
  81. yutani_flip(yctx, window);
  82. }
  83. int main(int argc, char * argv[]) {
  84. static struct option long_opts[] = {
  85. {"help", no_argument, 0, '?'},
  86. {0,0,0,0}
  87. };
  88. if (argc > 1) {
  89. /* Read some arguments */
  90. int index, c;
  91. while ((c = getopt_long(argc, argv, "h", long_opts, &index)) != -1) {
  92. if (!c) {
  93. if (long_opts[index].flag == 0) {
  94. c = long_opts[index].val;
  95. }
  96. }
  97. switch (c) {
  98. case 'h':
  99. usage(argv);
  100. exit(0);
  101. break;
  102. default:
  103. break;
  104. }
  105. }
  106. }
  107. yctx = yutani_init();
  108. if (!yctx) {
  109. fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
  110. return 1;
  111. }
  112. init_decorations();
  113. struct decor_bounds bounds;
  114. decor_get_bounds(NULL, &bounds);
  115. decor_left_width = bounds.left_width;
  116. decor_top_height = bounds.top_height;
  117. decor_right_width = bounds.right_width;
  118. decor_bottom_height = bounds.bottom_height;
  119. decor_width = bounds.width;
  120. decor_height = bounds.height;
  121. load_sprite(&img, argv[optind]);
  122. if (!img.width) {
  123. fprintf(stderr, "%s: failed to open image %s\n", argv[0], argv[optind]);
  124. return 1;
  125. }
  126. img.alpha = ALPHA_EMBEDDED;
  127. width = img.width;
  128. height = img.height;
  129. window = yutani_window_create(yctx, width + decor_width, height + decor_height);
  130. yutani_window_move(yctx, window, left, top);
  131. yutani_window_advertise_icon(yctx, window, APPLICATION_TITLE, "imgviewer");
  132. ctx = init_graphics_yutani_double_buffer(window);
  133. redraw();
  134. yutani_flip(yctx, window);
  135. int playing = 1;
  136. while (playing) {
  137. yutani_msg_t * m = yutani_poll(yctx);
  138. while (m) {
  139. if (menu_process_event(yctx, m)) {
  140. /* just decorations should be fine */
  141. decors();
  142. yutani_flip(yctx, window);
  143. }
  144. switch (m->type) {
  145. case YUTANI_MSG_KEY_EVENT:
  146. {
  147. struct yutani_msg_key_event * ke = (void*)m->data;
  148. if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
  149. playing = 0;
  150. }
  151. }
  152. break;
  153. case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
  154. {
  155. struct yutani_msg_window_focus_change * wf = (void*)m->data;
  156. yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
  157. if (win && win == window) {
  158. win->focused = wf->focused;
  159. decors();
  160. yutani_flip(yctx, window);
  161. }
  162. }
  163. break;
  164. case YUTANI_MSG_RESIZE_OFFER:
  165. {
  166. struct yutani_msg_window_resize * wr = (void*)m->data;
  167. resize_finish(wr->width, wr->height);
  168. }
  169. break;
  170. case YUTANI_MSG_WINDOW_MOUSE_EVENT:
  171. {
  172. struct yutani_msg_window_mouse_event * me = (void*)m->data;
  173. int result = decor_handle_event(yctx, m);
  174. switch (result) {
  175. case DECOR_CLOSE:
  176. playing = 0;
  177. break;
  178. case DECOR_RIGHT:
  179. /* right click in decoration, show appropriate menu */
  180. decor_show_default_menu(window, window->x + me->new_x, window->y + me->new_y);
  181. break;
  182. default:
  183. /* Other actions */
  184. break;
  185. }
  186. }
  187. break;
  188. case YUTANI_MSG_WINDOW_CLOSE:
  189. case YUTANI_MSG_SESSION_END:
  190. playing = 0;
  191. break;
  192. default:
  193. break;
  194. }
  195. free(m);
  196. m = yutani_poll_async(yctx);
  197. }
  198. }
  199. yutani_close(yctx, window);
  200. return 0;
  201. }