A Simple X Image Viewer
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
14 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. /* sxiv: main.c
  2. * Copyright (c) 2011 Bert Muennich <muennich at informatik.hu-berlin.de>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <sys/select.h>
  21. #include <X11/Xlib.h>
  22. #include <X11/Xutil.h>
  23. #include <X11/keysym.h>
  24. #include "sxiv.h"
  25. #include "image.h"
  26. #include "options.h"
  27. #include "window.h"
  28. void on_keypress(XEvent*);
  29. void on_buttonpress(XEvent*);
  30. void on_configurenotify(XEvent*);
  31. void update_title();
  32. static void (*handler[LASTEvent])(XEvent*) = {
  33. [KeyPress] = on_keypress,
  34. [ButtonPress] = on_buttonpress,
  35. [ConfigureNotify] = on_configurenotify
  36. };
  37. img_t img;
  38. win_t win;
  39. const char **filenames;
  40. int filecnt, fileidx;
  41. unsigned char timeout;
  42. #define TITLE_LEN 256
  43. char win_title[TITLE_LEN];
  44. void run() {
  45. int xfd;
  46. fd_set fds;
  47. struct timeval t;
  48. XEvent ev;
  49. timeout = 0;
  50. while (1) {
  51. if (timeout) {
  52. t.tv_sec = 0;
  53. t.tv_usec = 250;
  54. xfd = ConnectionNumber(win.env.dpy);
  55. FD_ZERO(&fds);
  56. FD_SET(xfd, &fds);
  57. if (!XPending(win.env.dpy) && !select(xfd + 1, &fds, 0, 0, &t)) {
  58. img_render(&img, &win);
  59. timeout = 0;
  60. }
  61. }
  62. if (!XNextEvent(win.env.dpy, &ev) && handler[ev.type])
  63. handler[ev.type](&ev);
  64. }
  65. }
  66. int main(int argc, char **argv) {
  67. int i;
  68. parse_options(argc, argv);
  69. if (!options->filecnt) {
  70. print_usage();
  71. exit(1);
  72. }
  73. if (!(filenames = (const char**) malloc(options->filecnt * sizeof(char*))))
  74. DIE("could not allocate memory");
  75. fileidx = 0;
  76. filecnt = 0;
  77. for (i = 0; i < options->filecnt; ++i) {
  78. if (!(img_load(&img, options->filenames[i]) < 0))
  79. filenames[filecnt++] = options->filenames[i];
  80. }
  81. if (!filecnt) {
  82. fprintf(stderr, "sxiv: no valid image filename given, aborting\n");
  83. exit(1);
  84. }
  85. win_open(&win);
  86. img_init(&img, &win);
  87. img_load(&img, filenames[fileidx]);
  88. img_render(&img, &win);
  89. update_title();
  90. run();
  91. cleanup();
  92. return 0;
  93. }
  94. void cleanup() {
  95. static int in = 0;
  96. if (!in++) {
  97. img_free(&img);
  98. win_close(&win);
  99. }
  100. }
  101. void on_keypress(XEvent *ev) {
  102. char key;
  103. KeySym keysym;
  104. int changed;
  105. if (!ev)
  106. return;
  107. XLookupString(&ev->xkey, &key, 1, &keysym, NULL);
  108. changed = 0;
  109. switch (keysym) {
  110. case XK_Escape:
  111. cleanup();
  112. exit(2);
  113. case XK_space:
  114. key = 'n';
  115. break;
  116. case XK_BackSpace:
  117. key = 'p';
  118. break;
  119. }
  120. switch (key) {
  121. case 'q':
  122. cleanup();
  123. exit(0);
  124. /* navigate image list */
  125. case 'n':
  126. if (fileidx + 1 < filecnt) {
  127. img_load(&img, filenames[++fileidx]);
  128. changed = 1;
  129. }
  130. break;
  131. case 'p':
  132. if (fileidx > 0) {
  133. img_load(&img, filenames[--fileidx]);
  134. changed = 1;
  135. }
  136. break;
  137. case '[':
  138. if (fileidx != 0) {
  139. fileidx = MAX(0, fileidx - 10);
  140. img_load(&img, filenames[fileidx]);
  141. changed = 1;
  142. }
  143. break;
  144. case ']':
  145. if (fileidx != filecnt - 1) {
  146. fileidx = MIN(fileidx + 10, filecnt - 1);
  147. img_load(&img, filenames[fileidx]);
  148. changed = 1;
  149. }
  150. break;
  151. case 'g':
  152. if (fileidx != 0) {
  153. fileidx = 0;
  154. img_load(&img, filenames[fileidx]);
  155. changed = 1;
  156. }
  157. break;
  158. case 'G':
  159. if (fileidx != filecnt - 1) {
  160. fileidx = filecnt - 1;
  161. img_load(&img, filenames[fileidx]);
  162. changed = 1;
  163. }
  164. break;
  165. /* zooming */
  166. case '+':
  167. case '=':
  168. changed = img_zoom_in(&img);
  169. break;
  170. case '-':
  171. changed = img_zoom_out(&img);
  172. break;
  173. /* panning */
  174. case 'h':
  175. changed = img_pan(&img, &win, PAN_LEFT);
  176. break;
  177. case 'j':
  178. changed = img_pan(&img, &win, PAN_DOWN);
  179. break;
  180. case 'k':
  181. changed = img_pan(&img, &win, PAN_UP);
  182. break;
  183. case 'l':
  184. changed = img_pan(&img, &win, PAN_RIGHT);
  185. break;
  186. /* rotation */
  187. case '<':
  188. changed = img_rotate_left(&img, &win);
  189. break;
  190. case '>':
  191. changed = img_rotate_right(&img, &win);
  192. break;
  193. /* control window */
  194. case 'f':
  195. win_toggle_fullscreen(&win);
  196. break;
  197. /* miscellaneous */
  198. case 'a':
  199. changed = img_toggle_antialias(&img);
  200. break;
  201. }
  202. if (changed) {
  203. img_render(&img, &win);
  204. update_title();
  205. timeout = 0;
  206. }
  207. }
  208. void on_buttonpress(XEvent *ev) {
  209. int changed;
  210. unsigned int mask;
  211. if (!ev)
  212. return;
  213. mask = CLEANMASK(ev->xbutton.state);
  214. changed = 0;
  215. switch (ev->xbutton.button) {
  216. case Button1:
  217. if (fileidx + 1 < filecnt) {
  218. img_load(&img, filenames[++fileidx]);
  219. changed = 1;
  220. }
  221. break;
  222. case Button3:
  223. if (fileidx > 0) {
  224. img_load(&img, filenames[--fileidx]);
  225. changed = 1;
  226. }
  227. break;
  228. case Button4:
  229. if (mask == ControlMask)
  230. changed = img_zoom_in(&img);
  231. else if (mask == ShiftMask)
  232. changed = img_pan(&img, &win, PAN_LEFT);
  233. else
  234. changed = img_pan(&img, &win, PAN_UP);
  235. break;
  236. case Button5:
  237. if (mask == ControlMask)
  238. changed = img_zoom_out(&img);
  239. else if (mask == ShiftMask)
  240. changed = img_pan(&img, &win, PAN_RIGHT);
  241. else
  242. changed = img_pan(&img, &win, PAN_DOWN);
  243. break;
  244. case 6:
  245. changed = img_pan(&img, &win, PAN_LEFT);
  246. break;
  247. case 7:
  248. changed = img_pan(&img, &win, PAN_RIGHT);
  249. break;
  250. }
  251. if (changed) {
  252. img_render(&img, &win);
  253. update_title();
  254. timeout = 0;
  255. }
  256. }
  257. void on_configurenotify(XEvent *ev) {
  258. if (!ev)
  259. return;
  260. if (win_configure(&win, &ev->xconfigure)) {
  261. img.checkpan = 1;
  262. timeout = 1;
  263. }
  264. }
  265. void update_title() {
  266. int n;
  267. n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] <%d%%> %s", fileidx + 1,
  268. filecnt, (int) (img.zoom * 100.0), filenames[fileidx]);
  269. if (n >= TITLE_LEN) {
  270. win_title[TITLE_LEN - 2] = '.';
  271. win_title[TITLE_LEN - 3] = '.';
  272. win_title[TITLE_LEN - 4] = '.';
  273. }
  274. win_set_title(&win, win_title);
  275. }