imgviewer.c 5.7 KB

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