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

404 строки
7.9 KiB

  1. /* sxiv: commands.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 it
  5. * under the terms of the GNU General Public License as published by the
  6. * Free Software Foundation; either version 2 of the License, or (at your
  7. * option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License along
  15. * with this program; if not, write to the Free Software Foundation, Inc.,
  16. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. */
  18. #define _POSIX_C_SOURCE 200112L /* for setenv(3) */
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #include <sys/wait.h>
  23. #include "commands.h"
  24. #include "image.h"
  25. #include "thumbs.h"
  26. #include "types.h"
  27. #include "util.h"
  28. void cleanup();
  29. void remove_file(int, unsigned char);
  30. void load_image(int);
  31. void redraw();
  32. void reset_cursor();
  33. void animate();
  34. void set_timeout(timeout_f, int, int);
  35. void reset_timeout(timeout_f);
  36. extern appmode_t mode;
  37. extern img_t img;
  38. extern tns_t tns;
  39. extern win_t win;
  40. extern fileinfo_t *files;
  41. extern int filecnt, fileidx;
  42. int it_quit(arg_t a) {
  43. cleanup();
  44. exit(0);
  45. }
  46. int it_switch_mode(arg_t a) {
  47. if (mode == MODE_IMAGE) {
  48. if (!tns.thumbs)
  49. tns_init(&tns, filecnt);
  50. img_close(&img, 0);
  51. reset_timeout(reset_cursor);
  52. tns.sel = fileidx;
  53. tns.dirty = 1;
  54. mode = MODE_THUMB;
  55. } else {
  56. load_image(tns.sel);
  57. mode = MODE_IMAGE;
  58. }
  59. return 1;
  60. }
  61. int it_toggle_fullscreen(arg_t a) {
  62. win_toggle_fullscreen(&win);
  63. set_timeout(redraw, TO_REDRAW_RESIZE, 0);
  64. if (mode == MODE_IMAGE)
  65. img.checkpan = 1;
  66. else
  67. tns.dirty = 1;
  68. return 0;
  69. }
  70. int it_reload_image(arg_t a) {
  71. if (mode == MODE_IMAGE) {
  72. load_image(fileidx);
  73. } else {
  74. win_set_cursor(&win, CURSOR_WATCH);
  75. if (!tns_load(&tns, tns.sel, &files[tns.sel], True, False)) {
  76. remove_file(tns.sel, 0);
  77. tns.dirty = 1;
  78. if (tns.sel >= tns.cnt)
  79. tns.sel = tns.cnt - 1;
  80. }
  81. }
  82. return 1;
  83. }
  84. int it_remove_image(arg_t a) {
  85. if (mode == MODE_IMAGE) {
  86. remove_file(fileidx, 1);
  87. load_image(fileidx >= filecnt ? filecnt - 1 : fileidx);
  88. return 1;
  89. } else if (tns.sel < tns.cnt) {
  90. remove_file(tns.sel, 1);
  91. tns.dirty = 1;
  92. if (tns.sel >= tns.cnt)
  93. tns.sel = tns.cnt - 1;
  94. return 1;
  95. } else {
  96. return 0;
  97. }
  98. }
  99. int i_navigate(arg_t a) {
  100. long n = (long) a;
  101. if (mode == MODE_IMAGE) {
  102. n += fileidx;
  103. if (n < 0)
  104. n = 0;
  105. if (n >= filecnt)
  106. n = filecnt - 1;
  107. if (n != fileidx) {
  108. load_image(n);
  109. return 1;
  110. }
  111. }
  112. return 0;
  113. }
  114. int it_first(arg_t a) {
  115. if (mode == MODE_IMAGE && fileidx != 0) {
  116. load_image(0);
  117. return 1;
  118. } else if (mode == MODE_THUMB && tns.sel != 0) {
  119. tns.sel = 0;
  120. tns.dirty = 1;
  121. return 1;
  122. } else {
  123. return 0;
  124. }
  125. }
  126. int it_last(arg_t a) {
  127. if (mode == MODE_IMAGE && fileidx != filecnt - 1) {
  128. load_image(filecnt - 1);
  129. return 1;
  130. } else if (mode == MODE_THUMB && tns.sel != tns.cnt - 1) {
  131. tns.sel = tns.cnt - 1;
  132. tns.dirty = 1;
  133. return 1;
  134. } else {
  135. return 0;
  136. }
  137. }
  138. int i_navigate_frame(arg_t a) {
  139. if (mode == MODE_IMAGE && !img.multi.animate)
  140. return img_frame_navigate(&img, (long) a);
  141. else
  142. return 0;
  143. }
  144. int i_toggle_animation(arg_t a) {
  145. int delay;
  146. if (mode != MODE_IMAGE)
  147. return 0;
  148. if (img.multi.animate) {
  149. reset_timeout(animate);
  150. img.multi.animate = 0;
  151. return 0;
  152. } else {
  153. delay = img_frame_animate(&img, 1);
  154. set_timeout(animate, delay, 1);
  155. return 1;
  156. }
  157. }
  158. int it_move(arg_t a) {
  159. direction_t dir = (direction_t) a;
  160. if (mode == MODE_IMAGE)
  161. return img_pan(&img, &win, dir, 0);
  162. else
  163. return tns_move_selection(&tns, &win, dir);
  164. }
  165. int i_pan_screen(arg_t a) {
  166. direction_t dir = (direction_t) a;
  167. if (mode == MODE_IMAGE)
  168. return img_pan(&img, &win, dir, 1);
  169. else
  170. return 0;
  171. }
  172. int i_pan_edge(arg_t a) {
  173. direction_t dir = (direction_t) a;
  174. if (mode == MODE_IMAGE)
  175. return img_pan_edge(&img, &win, dir);
  176. else
  177. return 0;
  178. }
  179. /* Xlib helper function for i_drag() */
  180. Bool is_motionnotify(Display *d, XEvent *e, XPointer a) {
  181. return e != NULL && e->type == MotionNotify;
  182. }
  183. int i_drag(arg_t a) {
  184. int dx = 0, dy = 0, i, ox, oy, x, y;
  185. unsigned int ui;
  186. Bool dragging = True, next = False;
  187. XEvent e;
  188. Window w;
  189. if (mode != MODE_IMAGE)
  190. return 0;
  191. if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui))
  192. return 0;
  193. win_set_cursor(&win, CURSOR_HAND);
  194. while (dragging) {
  195. if (!next)
  196. XMaskEvent(win.env.dpy,
  197. ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e);
  198. switch (e.type) {
  199. case ButtonPress:
  200. case ButtonRelease:
  201. dragging = False;
  202. break;
  203. case MotionNotify:
  204. x = e.xmotion.x;
  205. y = e.xmotion.y;
  206. if (x >= 0 && x <= win.w && y >= 0 && y <= win.h) {
  207. dx += x - ox;
  208. dy += y - oy;
  209. }
  210. ox = x;
  211. oy = y;
  212. break;
  213. }
  214. if (dragging)
  215. next = XCheckIfEvent(win.env.dpy, &e, is_motionnotify, None);
  216. if ((!dragging || !next) && (dx != 0 || dy != 0)) {
  217. if (img_move(&img, &win, dx, dy))
  218. img_render(&img, &win);
  219. dx = dy = 0;
  220. }
  221. }
  222. win_set_cursor(&win, CURSOR_ARROW);
  223. set_timeout(reset_cursor, TO_CURSOR_HIDE, 1);
  224. reset_timeout(redraw);
  225. return 0;
  226. }
  227. int i_zoom(arg_t a) {
  228. long scale = (long) a;
  229. if (mode != MODE_IMAGE)
  230. return 0;
  231. if (scale > 0)
  232. return img_zoom_in(&img, &win);
  233. else if (scale < 0)
  234. return img_zoom_out(&img, &win);
  235. else
  236. return img_zoom(&img, &win, 1.0);
  237. }
  238. int i_fit_to_win(arg_t a) {
  239. int ret;
  240. if (mode == MODE_IMAGE) {
  241. if ((ret = img_fit_win(&img, &win)))
  242. img_center(&img, &win);
  243. return ret;
  244. } else {
  245. return 0;
  246. }
  247. }
  248. int i_fit_to_img(arg_t a) {
  249. int ret, x, y;
  250. unsigned int w, h;
  251. if (mode == MODE_IMAGE) {
  252. x = MAX(0, win.x + img.x);
  253. y = MAX(0, win.y + img.y);
  254. w = img.w * img.zoom;
  255. h = img.h * img.zoom;
  256. if ((ret = win_moveresize(&win, x, y, w, h))) {
  257. img.x = x - win.x;
  258. img.y = y - win.y;
  259. }
  260. return ret;
  261. } else {
  262. return 0;
  263. }
  264. }
  265. int i_rotate(arg_t a) {
  266. direction_t dir = (direction_t) a;
  267. if (mode == MODE_IMAGE) {
  268. if (dir == DIR_LEFT) {
  269. img_rotate_left(&img, &win);
  270. return 1;
  271. } else if (dir == DIR_RIGHT) {
  272. img_rotate_right(&img, &win);
  273. return 1;
  274. }
  275. }
  276. return 0;
  277. }
  278. int i_toggle_antialias(arg_t a) {
  279. if (mode == MODE_IMAGE) {
  280. img_toggle_antialias(&img);
  281. return 1;
  282. } else {
  283. return 0;
  284. }
  285. }
  286. int it_toggle_alpha(arg_t a) {
  287. img.alpha ^= 1;
  288. tns.alpha = img.alpha;
  289. if (mode == MODE_THUMB)
  290. tns.dirty = 1;
  291. return 1;
  292. }
  293. int it_open_with(arg_t a) {
  294. const char *prog = (const char*) a;
  295. pid_t pid;
  296. if (!prog || !*prog)
  297. return 0;
  298. if((pid = fork()) == 0) {
  299. execlp(prog, prog,
  300. files[mode == MODE_IMAGE ? fileidx : tns.sel].path, NULL);
  301. warn("could not exec: %s", prog);
  302. exit(1);
  303. } else if (pid < 0) {
  304. warn("could not fork. program was: %s", prog);
  305. }
  306. return 0;
  307. }
  308. int it_shell_cmd(arg_t a) {
  309. int n, status;
  310. const char *cmdline = (const char*) a;
  311. pid_t pid;
  312. if (!cmdline || !*cmdline)
  313. return 0;
  314. n = mode == MODE_IMAGE ? fileidx : tns.sel;
  315. if (setenv("SXIV_IMG", files[n].path, 1) < 0) {
  316. warn("could not change env.-variable: SXIV_IMG. command line was: %s",
  317. cmdline);
  318. return 0;
  319. }
  320. if ((pid = fork()) == 0) {
  321. execl("/bin/sh", "/bin/sh", "-c", cmdline, NULL);
  322. warn("could not exec: /bin/sh");
  323. exit(1);
  324. } else if (pid < 0) {
  325. warn("could not fork. command line was: %s", cmdline);
  326. return 0;
  327. }
  328. win_set_cursor(&win, CURSOR_WATCH);
  329. waitpid(pid, &status, 0);
  330. if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
  331. warn("child exited with non-zero return value: %d. command line was: %s",
  332. WEXITSTATUS(status), cmdline);
  333. if (mode == MODE_IMAGE) {
  334. img_close(&img, 1);
  335. load_image(fileidx);
  336. }
  337. if (!tns_load(&tns, n, &files[n], True, mode == MODE_IMAGE) &&
  338. mode == MODE_THUMB)
  339. {
  340. remove_file(tns.sel, 0);
  341. tns.dirty = 1;
  342. if (tns.sel >= tns.cnt)
  343. tns.sel = tns.cnt - 1;
  344. }
  345. return 1;
  346. }