Example #1
0
winwidget winwidget_create_from_file(gib_list * list, char *name, char type)
{
	winwidget ret = NULL;
	feh_file *file = FEH_FILE(list->data);

	if (!file || !file->filename)
		return(NULL);

	ret = winwidget_allocate();
	ret->file = list;
	ret->type = type;
	if (name)
		ret->name = estrdup(name);
	else
		ret->name = estrdup(file->filename);

	if (winwidget_loadimage(ret, file) == 0) {
		winwidget_destroy(ret);
		return(NULL);
	}

	if (!ret->win) {
		ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
		ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);
		D(("image is %dx%d pixels, format %s\n", ret->w, ret->h, gib_imlib_image_format(ret->im)));
		if (opt.full_screen)
			ret->full_screen = True;
		winwidget_create_window(ret, ret->w, ret->h);
		winwidget_render_image(ret, 1, 0);
	}

	return(ret);
}
Example #2
0
File: main.c Project: braneed/scrot
Imlib_Image
create_transparent_image(Imlib_Image w_image, Imlib_Image b_image)
{
  int w, h;
  DATA32 *dst_data, *src_data;
  imlib_context_set_image(w_image);
  dst_data = imlib_image_get_data();
  imlib_context_set_image(b_image);
  src_data = imlib_image_get_data();
  h = gib_imlib_image_get_height(w_image);
  w = gib_imlib_image_get_width(w_image);

  unsigned long i;
  for(i=0; i<w*h; i++)
    if(dst_data[i] != src_data[i])
    {
      DATA32 alpha;
      alpha = (src_data[i] & 0xff) - (dst_data[i] & 0xff);
      alpha = (alpha << 24) & 0xff000000;
      dst_data[i] = (src_data[i] & 0xffffff) | alpha;
    }
  Imlib_Image ret_img;
  ret_img = imlib_create_image_using_data(w, h, dst_data);
  imlib_context_set_image(ret_img);
  imlib_image_set_has_alpha(1);
  return ret_img;
}
Example #3
0
winwidget winwidget_create_from_image(Imlib_Image im, char *name, char type)
{
	winwidget ret = NULL;

	if (im == NULL)
		return(NULL);

	ret = winwidget_allocate();
	ret->type = type;

	ret->im = im;
	ret->w = ret->im_w = gib_imlib_image_get_width(ret->im);
	ret->h = ret->im_h = gib_imlib_image_get_height(ret->im);

	if (name)
		ret->name = estrdup(name);
	else
		ret->name = estrdup(PACKAGE);

	if (opt.full_screen && (type != WIN_TYPE_THUMBNAIL))
		ret->full_screen = True;
	winwidget_create_window(ret, ret->w, ret->h);
	winwidget_render_image(ret, 1, 0);

	return(ret);
}
Example #4
0
File: main.c Project: braneed/scrot
Imlib_Image
stalk_image_concat(gib_list * images)
{
  int tot_w = 0, max_h = 0, w, h;
  int x = 0;
  gib_list *l, *item;
  Imlib_Image ret, im;

  if (gib_list_length(images) == 0)
    return NULL;

  l = images;
  while (l) {
    im = (Imlib_Image) l->data;
    h = gib_imlib_image_get_height(im);
    w = gib_imlib_image_get_width(im);
    if (h > max_h)
      max_h = h;
    tot_w += w;
    l = l->next;
  }
  ret = imlib_create_image(tot_w, max_h);
  gib_imlib_image_fill_rectangle(ret, 0, 0, tot_w, max_h, 255, 0, 0, 0);
  l = images;
  while (l) {
    im = (Imlib_Image) l->data;
    item = l;
    l = l->next;
    h = gib_imlib_image_get_height(im);
    w = gib_imlib_image_get_width(im);
    gib_imlib_blend_image_onto_image(ret, im, 0, 0, 0, w, h, x, 0, w, h, 1, 0,
                                     0);
    x += w;
    gib_imlib_free_image_and_decache(im);
    free(item);
  }
  return ret;
}
Example #5
0
File: menu.c Project: talisein/feh
void feh_menu_draw_menu_bg(feh_menu * m, Imlib_Image im, int ox, int oy)
{
	int w, h;

	w = gib_imlib_image_get_width(im);
	h = gib_imlib_image_get_height(im);

	if (m->bg)
		gib_imlib_blend_image_onto_image(im, m->bg, 0, ox, oy, w, h, 0, 0, w, h, 0, 0, 0);
	else
		gib_imlib_image_fill_rectangle(im, 0, 0, w, h, 205, 203, 176, 255);

	return;
}
Example #6
0
File: menu.c Project: talisein/feh
void feh_menu_draw_to_buf(feh_menu * m, Imlib_Image im, int ox, int oy)
{
	feh_menu_item *i;
	int w, h;

	w = gib_imlib_image_get_width(im);
	h = gib_imlib_image_get_height(im);

	feh_menu_draw_menu_bg(m, im, ox, oy);

	for (i = m->items; i; i = i->next) {
		if (RECTS_INTERSECT(i->x, i->y, i->w, i->h, ox, oy, w, h))
			feh_menu_draw_item(i, im, ox, oy);
	}
	return;
}
Example #7
0
/* TODO s/bit/lot */
void init_thumbnail_mode(void)
{
	/* moved to thumbnail_data:
	   Imlib_Image im_main;
	   Imlib_Image bg_im = NULL;
	   Imlib_Font fn = NULL;
	   Imlib_Font title_fn = NULL;

	   int w = 800, h = 600;
	   int bg_w = 0, bg_h = 0;

	   int text_area_w, text_area_h;
	   int max_column_w = 0;
	 */

	Imlib_Image im_temp;
	int ww = 0, hh = 0, www, hhh, xxx, yyy;
	int x = 0, y = 0;
	winwidget winwid = NULL;
	Imlib_Image im_thumb = NULL;
	unsigned char trans_bg = 0;
	int title_area_h = 0;
	int tw = 0, th = 0;
	int fw_name, fw_size, fw_dim, fh;
	int thumbnailcount = 0;
	feh_file *file = NULL;
	gib_list *l, *last = NULL;
	int lines;
	int index_image_width, index_image_height;
	int x_offset_name = 0, x_offset_dim = 0, x_offset_size = 0;
	char *s;
	unsigned int thumb_counter = 0;

	/* initialize thumbnail mode data */
	td.im_main = NULL;
	td.im_bg = NULL;
	td.font_main = NULL;
	td.font_title = NULL;

	td.w = 640;
	td.h = 480;
	td.bg_w = 0;
	td.bg_h = 0;
	td.thumb_tot_h = 0;
	td.text_area_w = 0;
	td.text_area_h = 0;

	td.vertical = 0;
	td.max_column_w = 0;

	mode = "thumbnail";

	if (opt.font)
		td.font_main = gib_imlib_load_font(opt.font);

	if (!td.font_main)
		td.font_main = gib_imlib_load_font(DEFAULT_FONT);

	if (opt.title_font) {
		int fh, fw;

		td.font_title = gib_imlib_load_font(opt.title_font);
		gib_imlib_get_text_size(td.font_title, "W", NULL, &fw, &fh,
				IMLIB_TEXT_TO_RIGHT);
		title_area_h = fh + 4;
	} else
		td.font_title = imlib_load_font(DEFAULT_FONT_TITLE);

	if ((!td.font_main) || (!td.font_title))
		eprintf("Error loading fonts");

	/* Work out how tall the font is */
	gib_imlib_get_text_size(td.font_main, "W", NULL, &tw, &th,
			IMLIB_TEXT_TO_RIGHT);
	/* For now, allow room for the right number of lines with small gaps */
	td.text_area_h = ((th + 2) * (opt.index_show_name + opt.index_show_size +
				opt.index_show_dim)) + 5;

	/* This includes the text area for index data */
	td.thumb_tot_h = opt.thumb_h + td.text_area_h;

	/* Use bg image dimensions for default size */
	if (opt.bg && opt.bg_file) {
		if (!strcmp(opt.bg_file, "trans"))
			trans_bg = 1;
		else {

			D(3, ("Time to apply a background to blend onto\n"));
			if (feh_load_image_char(&td.im_bg, opt.bg_file) != 0) {
				td.bg_w = gib_imlib_image_get_width(td.im_bg);
				td.bg_h = gib_imlib_image_get_height(td.im_bg);
			}
		}
	}

	/* figure out geometry for the main window and entries */
	feh_thumbnail_calculate_geometry();

	index_image_width = td.w;
	index_image_height = td.h + title_area_h;
	td.im_main = imlib_create_image(index_image_width, index_image_height);
	gib_imlib_image_set_has_alpha(td.im_main, 1);

	if (!td.im_main)
		eprintf("Imlib error creating index image, are you low on RAM?");

	if (td.im_bg)
		gib_imlib_blend_image_onto_image(td.im_main, td.im_bg,
						 gib_imlib_image_has_alpha
						 (td.im_bg), 0, 0, td.bg_w, td.bg_h, 0, 0,
						 td.w, td.h, 1, 0, 0);
	else if (trans_bg) {
		gib_imlib_image_fill_rectangle(td.im_main, 0, 0, td.w,
				td.h + title_area_h, 0, 0, 0, 0);
		gib_imlib_image_set_has_alpha(td.im_main, 1);
	} else {
		/* Colour the background */
		gib_imlib_image_fill_rectangle(td.im_main, 0, 0, td.w,
				td.h + title_area_h, 0, 0, 0, 255);
	}

	/* Create title now */

	if (!opt.title)
		s = estrdup(PACKAGE " [thumbnail mode]");
	else
		s = estrdup(feh_printf(opt.title, NULL));

	if (opt.display) {
		winwid = winwidget_create_from_image(td.im_main, s, WIN_TYPE_THUMBNAIL);
		winwidget_show(winwid);
	}

	/* make sure we have an ~/.thumbnails/normal directory for storing
	   permanent thumbnails */
	td.cache_thumbnails = opt.cache_thumbnails;

	if (td.cache_thumbnails) {
		if (opt.thumb_w > opt.thumb_h)
			td.cache_dim = opt.thumb_w;
		else
			td.cache_dim = opt.thumb_h;

		if (td.cache_dim > 256) {
			/* No caching as specified by standard. Sort of. */
			td.cache_thumbnails = 0;
		} else if (td.cache_dim > 128) {
			td.cache_dim = 256;
			td.cache_dir = estrdup("large");
		} else {
			td.cache_dim = 128;
			td.cache_dir = estrdup("normal");
		}
		feh_thumbnail_setup_thumbnail_dir();
	}

	for (l = filelist; l; l = l->next) {
		file = FEH_FILE(l->data);
		if (last) {
			filelist = feh_file_remove_from_list(filelist, last);
			last = NULL;
		}
		D(4, ("About to load image %s\n", file->filename));
		/*      if (feh_load_image(&im_temp, file) != 0) */
		if (feh_thumbnail_get_thumbnail(&im_temp, file) != 0) {
			if (opt.verbose)
				feh_display_status('.');
			D(4, ("Successfully loaded %s\n", file->filename));
			www = opt.thumb_w;
			hhh = opt.thumb_h;
			ww = gib_imlib_image_get_width(im_temp);
			hh = gib_imlib_image_get_height(im_temp);
			thumbnailcount++;
			if (gib_imlib_image_has_alpha(im_temp))
				imlib_context_set_blend(1);
			else
				imlib_context_set_blend(0);

			if (opt.aspect) {
				double ratio = 0.0;

				/* Keep the aspect ratio for the thumbnail */
				ratio = ((double) ww / hh) / ((double) www / hhh);

				if (ratio > 1.0)
					hhh = opt.thumb_h / ratio;
				else if (ratio != 1.0)
					www = opt.thumb_w * ratio;
			}

			if ((!opt.stretch) && ((www > ww) || (hhh > hh))) {
				/* Don't make the image larger unless stretch is specified */
				www = ww;
				hhh = hh;
			}

			im_thumb = gib_imlib_create_cropped_scaled_image(im_temp, 0, 0,
					ww, hh, www, hhh, 1);
			gib_imlib_free_image_and_decache(im_temp);

			if (opt.alpha) {
				DATA8 atab[256];

				D(3, ("Applying alpha options\n"));
				gib_imlib_image_set_has_alpha(im_thumb, 1);
				memset(atab, opt.alpha_level, sizeof(atab));
				gib_imlib_apply_color_modifier_to_rectangle
				    (im_thumb, 0, 0, www, hhh, NULL, NULL, NULL, atab);
			}

			td.text_area_w = opt.thumb_w;
			/* Now draw on the info text */
			if (opt.index_show_name) {
				gib_imlib_get_text_size(td.font_main, file->name, NULL,
						&fw_name, &fh, IMLIB_TEXT_TO_RIGHT);
				if (fw_name > td.text_area_w)
					td.text_area_w = fw_name;
			}
			if (opt.index_show_dim) {
				gib_imlib_get_text_size(td.font_main,
							create_index_dimension_string(ww, hh),
							NULL, &fw_dim, &fh, IMLIB_TEXT_TO_RIGHT);
				if (fw_dim > td.text_area_w)
					td.text_area_w = fw_dim;
			}
			if (opt.index_show_size) {
				gib_imlib_get_text_size(td.font_main,
							create_index_size_string(file->filename),
							NULL, &fw_size, &fh, IMLIB_TEXT_TO_RIGHT);
				if (fw_size > td.text_area_w)
					td.text_area_w = fw_size;
			}
			if (td.text_area_w > opt.thumb_w)
				td.text_area_w += 5;

			/* offsets for centering text */
			x_offset_name = (td.text_area_w - fw_name) / 2;
			x_offset_dim = (td.text_area_w - fw_dim) / 2;
			x_offset_size = (td.text_area_w - fw_size) / 2;

			if (td.vertical) {
				if (td.text_area_w > td.max_column_w)
					td.max_column_w = td.text_area_w;
				if (y > td.h - td.thumb_tot_h) {
					y = 0;
					x += td.max_column_w;
					td.max_column_w = 0;
				}
				if (x > td.w - td.text_area_w)
					break;
			} else {
				if (x > td.w - td.text_area_w) {
					x = 0;
					y += td.thumb_tot_h;
				}
				if (y > td.h - td.thumb_tot_h)
					break;
			}

			/* center image relative to the text below it (if any) */
			xxx = x + ((td.text_area_w - www) / 2);
			yyy = y;

			if (opt.aspect)
				yyy += (opt.thumb_h - hhh) / 2;

			/* Draw now */
			gib_imlib_blend_image_onto_image(td.im_main,
							 im_thumb,
							 gib_imlib_image_has_alpha
							 (im_thumb), 0, 0,
							 www, hhh, xxx,
							 yyy, www, hhh, 1,
							 gib_imlib_image_has_alpha(im_thumb), 0);

			thumbnails = gib_list_add_front(thumbnails,
					feh_thumbnail_new(file, xxx, yyy, www, hhh));

			gib_imlib_free_image_and_decache(im_thumb);

			lines = 0;
			if (opt.index_show_name)
				gib_imlib_text_draw(td.im_main,
						td.font_main, NULL,
						x + x_offset_name,
						y + opt.thumb_h + (lines++ * (th + 2)) + 2,
						file->name, IMLIB_TEXT_TO_RIGHT,
						255, 255, 255, 255);
			if (opt.index_show_dim)
				gib_imlib_text_draw(td.im_main,
						td.font_main, NULL,
						x + x_offset_dim,
						y + opt.thumb_h + (lines++ * (th + 2)) + 2,
						create_index_dimension_string(ww, hh),
						IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
			if (opt.index_show_size)
				gib_imlib_text_draw(td.im_main,
						td.font_main, NULL,
						x + x_offset_size,
						y + opt.thumb_h + (lines++ * (th + 2)) + 2,
						create_index_size_string(file->filename),
						IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);

			if (td.vertical)
				y += td.thumb_tot_h;
			else
				x += td.text_area_w;
		} else {
			if (opt.verbose)
				feh_display_status('x');
			last = l;
		}
		if (opt.display) {
			/* thumb_counter is unsigned, so no need to catch overflows */
			if (++thumb_counter == opt.thumb_redraw) {
				winwidget_render_image(winwid, 0, 0);
				thumb_counter = 0;
			}
			if (!feh_main_iteration(0))
				exit(0);
		}
	}

	if (thumb_counter != 0)
		winwidget_render_image(winwid, 0, 0);

	if (opt.verbose)
		fprintf(stdout, "\n");

	if (opt.title_font) {
		int fw, fh, fx, fy;
		char *s;

		s = create_index_title_string(thumbnailcount, td.w, td.h);
		gib_imlib_get_text_size(td.font_title, s, NULL, &fw, &fh,
				IMLIB_TEXT_TO_RIGHT);
		fx = (index_image_width - fw) >> 1;
		fy = index_image_height - fh - 2;
		gib_imlib_text_draw(td.im_main, td.font_title, NULL, fx,
				fy, s, IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
	}
Example #8
0
File: menu.c Project: EvinceMoi/feh
void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, unsigned short data)
{
	char *path;

	switch (action) {
		case CB_BG_TILED:
			path = FEH_FILE(m->fehwin->file->data)->filename;
			feh_wm_set_bg(path, m->fehwin->im, 0, 0, 0, data, 0);
			break;
		case CB_BG_SCALED:
			path = FEH_FILE(m->fehwin->file->data)->filename;
			feh_wm_set_bg(path, m->fehwin->im, 0, 1, 0, data, 0);
			break;
		case CB_BG_CENTERED:
			path = FEH_FILE(m->fehwin->file->data)->filename;
			feh_wm_set_bg(path, m->fehwin->im, 1, 0, 0, data, 0);
			break;
		case CB_BG_FILLED:
			path = FEH_FILE(m->fehwin->file->data)->filename;
			feh_wm_set_bg(path, m->fehwin->im, 0, 0, 1, data, 0);
			break;
		case CB_BG_TILED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 0, data, 0);
			break;
		case CB_BG_SCALED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 1, 0, data, 0);
			break;
		case CB_BG_CENTERED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 1, 0, 0, data, 0);
			break;
		case CB_BG_FILLED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 1, data, 0);
			break;
		case CB_CLOSE:
			winwidget_destroy(m->fehwin);
			break;
		case CB_EXIT:
			winwidget_destroy_all();
			break;
		case CB_RESET:
			if (m->fehwin->has_rotated) {
				m->fehwin->im_w = gib_imlib_image_get_width(m->fehwin->im);
				m->fehwin->im_h = gib_imlib_image_get_height(m->fehwin->im);
				winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h);
			}
			winwidget_reset_image(m->fehwin);
			winwidget_render_image(m->fehwin, 1, 0);
			break;
		case CB_RELOAD:
			feh_reload_image(m->fehwin, 0, 1);
			break;
		case CB_REMOVE:
			feh_filelist_image_remove(m->fehwin, 0);
			break;
		case CB_DELETE:
			feh_filelist_image_remove(m->fehwin, 1);
			break;
		case CB_REMOVE_THUMB:
			feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 0);
			feh_filelist_image_remove(m->fehwin, 0);
			break;
		case CB_DELETE_THUMB:
			feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 1);
			feh_filelist_image_remove(m->fehwin, 1);
			break;
		case CB_SORT_FILENAME:
			filelist = gib_list_sort(filelist, feh_cmp_filename);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
			}
			break;
		case CB_SORT_IMAGENAME:
			filelist = gib_list_sort(filelist, feh_cmp_name);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
			}
			break;
		case CB_SORT_FILESIZE:
			filelist = gib_list_sort(filelist, feh_cmp_size);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
			}
			break;
		case CB_SORT_RANDOMIZE:
			filelist = gib_list_randomize(filelist);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST, 1);
			}
			break;
		case CB_FIT:
			winwidget_size_to_image(m->fehwin);
			break;
		case CB_EDIT_ROTATE:
			feh_edit_inplace(m->fehwin, data);
			break;
		case CB_SAVE_IMAGE:
			slideshow_save_image(m->fehwin);
			break;
		case CB_SAVE_FILELIST:
			feh_save_filelist();
			break;
		case CB_OPT_DRAW_FILENAME:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.draw_filename = TRUE;
			else
				opt.draw_filename = FALSE;
			winwidget_rerender_all(0);
			break;
		case CB_OPT_DRAW_ACTIONS:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.draw_actions = TRUE;
			else
				opt.draw_actions = FALSE;
			winwidget_rerender_all(0);
			break;
		case CB_OPT_KEEP_HTTP:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.keep_http = TRUE;
			else
				opt.keep_http = FALSE;
			break;
		case CB_OPT_FREEZE_WINDOW:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i)) {
				opt.geom_flags = (WidthValue | HeightValue);
				opt.geom_w = m->fehwin->w;
				opt.geom_h = m->fehwin->h;
			} else {
				opt.geom_flags = 0;
			}
			break;
		case CB_OPT_FULLSCREEN:
			feh_menu_cb_opt_fullscreen(m, i);
			break;
		case CB_OPT_AUTO_ZOOM:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.zoom_mode = ZOOM_MODE_MAX;
			else
				opt.zoom_mode = 0;
			winwidget_rerender_all(1);
			break;
		case CB_OPT_KEEP_ZOOM_VP:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.keep_zoom_vp = 1;
			else
				opt.keep_zoom_vp = 0;
			break;
	}
	return;
}
Example #9
0
/* TODO s/bit/lot */
void init_index_mode(void)
{
	Imlib_Image im_main;
	Imlib_Image im_temp;
	int w = 800, h = 600, ww = 0, hh = 0, www, hhh, xxx, yyy;
	int x = 0, y = 0;
	int bg_w = 0, bg_h = 0;
	winwidget winwid = NULL;
	Imlib_Image bg_im = NULL, im_thumb = NULL;
	int tot_thumb_h;
	int text_area_h = 50;
	int title_area_h = 0;
	Imlib_Font fn = NULL;
	Imlib_Font title_fn = NULL;
	int text_area_w = 0;
	int tw = 0, th = 0;
	int fw, fh;
	int vertical = 0;
	int max_column_w = 0;
	int thumbnailcount = 0;
	gib_list *l = NULL, *last = NULL;
	feh_file *file = NULL;
	int lineno;
	unsigned char trans_bg = 0;
	int index_image_width, index_image_height;
	char *s;
	gib_list *line, *lines;

	if (opt.montage) {
		mode = "montage";
	} else {
		mode = "index";
	}

	if (opt.font)
		fn = gib_imlib_load_font(opt.font);

	if (!fn)
		fn = gib_imlib_load_font(DEFAULT_FONT);

	if (opt.title_font) {

		title_fn = gib_imlib_load_font(opt.title_font);
		if (!title_fn)
			title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE);

		gib_imlib_get_text_size(title_fn, "W", NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT);
		title_area_h = fh + 4;
	} else
		title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE);

	if ((!fn) || (!title_fn))
		eprintf("Error loading fonts");

	/* Work out how tall the font is */
	gib_imlib_get_text_size(fn, "W", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT);
	get_index_string_dim(NULL, fn, &fw, &fh);
	/* For now, allow room for the right number of lines with small gaps */
	text_area_h = fh + 5;

	/* This includes the text area for index data */
	tot_thumb_h = opt.thumb_h + text_area_h;

	/* Use bg image dimensions for default size */
	if (opt.bg && opt.bg_file) {
		if (!strcmp(opt.bg_file, "trans"))
			trans_bg = 1;
		else {
			D(("Time to apply a background to blend onto\n"));
			if (feh_load_image_char(&bg_im, opt.bg_file) != 0) {
				bg_w = gib_imlib_image_get_width(bg_im);
				bg_h = gib_imlib_image_get_height(bg_im);
			}
		}
	}

	if (!opt.limit_w && !opt.limit_h) {
		if (bg_im) {
			opt.limit_w = bg_w;
			opt.limit_h = bg_h;
		} else
			opt.limit_w = 800;
	}

	/* Here we need to whiz through the files, and look at the filenames and
	   info in the selected font, work out how much space we need, and
	   calculate the size of the image we will require */

	if (opt.limit_w) {
		w = opt.limit_w;

		index_calculate_height(fn, w, &h, &tot_thumb_h);

		if (opt.limit_h) {
			if (h > opt.limit_h)
				weprintf(
					"The image size you specified (%dx%d) is not large\n"
					"enough to hold all %d thumbnails. To fit all the thumbnails,\n"
					"either decrease their size, choos e asmaller font,\n"
					"or use a larger image (like %dx%d)",
					opt.limit_w, opt.limit_h, filelist_len, w, h);
			h = opt.limit_h;
		}
	} else if (opt.limit_h) {
		vertical = 1;
		h = opt.limit_h;

		index_calculate_width(fn, &w, h, &tot_thumb_h);
	}

	index_image_width = w;
	index_image_height = h + title_area_h;
	im_main = imlib_create_image(index_image_width, index_image_height);

	if (!im_main)
		eprintf("Imlib error creating index image, are you low on RAM?");

	if (bg_im)
		gib_imlib_blend_image_onto_image(im_main, bg_im,
						 gib_imlib_image_has_alpha
						 (bg_im), 0, 0, bg_w, bg_h, 0, 0, w, h, 1, 0, 0);
	else if (trans_bg) {
		gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h + title_area_h, 0, 0, 0, 0);
		gib_imlib_image_set_has_alpha(im_main, 1);
	} else {
		/* Colour the background */
		gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h + title_area_h, 0, 0, 0, 255);
	}

	/* Create the window title at this point */

	if (!opt.title)
		s = estrdup(PACKAGE " [index mode]");
	else
		s = estrdup(feh_printf(opt.title, NULL));

	if (opt.display) {
		winwid = winwidget_create_from_image(im_main, s, WIN_TYPE_SINGLE);
		winwidget_show(winwid);
	}

	for (l = filelist; l; l = l->next) {
		file = FEH_FILE(l->data);
		if (last) {
			filelist = feh_file_remove_from_list(filelist, last);
			last = NULL;
		}
		D(("About to load image %s\n", file->filename));
		if (feh_load_image(&im_temp, file) != 0) {
			if (opt.verbose)
				feh_display_status('.');
			D(("Successfully loaded %s\n", file->filename));
			www = opt.thumb_w;
			hhh = opt.thumb_h;
			ww = gib_imlib_image_get_width(im_temp);
			hh = gib_imlib_image_get_height(im_temp);
			thumbnailcount++;

			if (opt.aspect) {
				double ratio = 0.0;

				/* Keep the aspect ratio for the thumbnail */
				ratio = ((double) ww / hh) / ((double) www / hhh);

				if (ratio > 1.0)
					hhh = opt.thumb_h / ratio;
				else if (ratio != 1.0)
					www = opt.thumb_w * ratio;
			}

			if ((!opt.stretch) && ((www > ww) || (hhh > hh))) {
				/* Don't make the image larger unless stretch is specified */
				www = ww;
				hhh = hh;
			}

			im_thumb = gib_imlib_create_cropped_scaled_image(im_temp, 0, 0, ww, hh, www, hhh, 1);
			gib_imlib_free_image_and_decache(im_temp);

			if (opt.alpha) {
				DATA8 atab[256];

				D(("Applying alpha options\n"));
				gib_imlib_image_set_has_alpha(im_thumb, 1);
				memset(atab, opt.alpha_level, sizeof(atab));
				gib_imlib_apply_color_modifier_to_rectangle
				    (im_thumb, 0, 0, www, hhh, NULL, NULL, NULL, atab);
			}

			text_area_w = opt.thumb_w;
			/* Now draw on the info text */
			if (opt.index_info) {
				get_index_string_dim(file, fn, &fw, &fh);
				if (fw > text_area_w)
					text_area_w = fw;
			}
			if (text_area_w > opt.thumb_w)
				text_area_w += 5;

			if (vertical) {
				if (text_area_w > max_column_w)
					max_column_w = text_area_w;
				if (y > h - tot_thumb_h) {
					y = 0;
					x += max_column_w;
					max_column_w = 0;
				}
				if (x > w - text_area_w)
					break;
			} else {
				if (x > w - text_area_w) {
					x = 0;
					y += tot_thumb_h;
				}
				if (y > h - tot_thumb_h)
					break;
			}

			/* center image relative to the text below it (if any) */
			xxx = x + ((text_area_w - www) / 2);
			yyy = y;

			if (opt.aspect)
				yyy += (opt.thumb_h - hhh) / 2;

			/* Draw now */
			gib_imlib_blend_image_onto_image(im_main, im_thumb,
							 gib_imlib_image_has_alpha
							 (im_thumb), 0, 0,
							 www, hhh, xxx,
							 yyy, www, hhh, 1, gib_imlib_image_has_alpha(im_thumb), 0);

			gib_imlib_free_image_and_decache(im_thumb);

			lineno = 0;
			if (opt.index_info) {
				line = lines = feh_wrap_string(create_index_string(file),
						opt.thumb_w * 3, fn, NULL);

				while (line) {
					gib_imlib_get_text_size(fn, (char *) line->data,
							NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT);
					gib_imlib_text_draw(im_main, fn, NULL,
							x + ((text_area_w - fw) >> 1),
							y + opt.thumb_h + (lineno++ * (th + 2)) + 2,
							(char *) line->data,
							IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
					line = line->next;
				}
				gib_list_free_and_data(lines);
			}

			if (vertical)
				y += tot_thumb_h;
			else
				x += text_area_w;

		} else {
			if (opt.verbose)
Example #10
0
File: main.c Project: braneed/scrot
char *
im_printf(char *str, struct tm *tm,
          char *filename_im,
          char *filename_thumb,
          Imlib_Image im)
{
  char *c;
  char buf[20];
  char ret[4096];
  char strf[4096];
  char *tmp;
  struct stat st;

  ret[0] = '\0';
  strftime(strf, 4095, str, tm);

  for (c = strf; *c != '\0'; c++) {
    if (*c == '$') {
      c++;
      switch (*c) {
        case 'f':
          if (filename_im)
            strcat(ret, filename_im);
          break;
        case 'm': /* t was allready taken, so m as in mini */
          if (filename_thumb)
            strcat(ret, filename_thumb);
          break;
        case 'n':
          if (filename_im) {
            tmp = strrchr(filename_im, '/');
            if (tmp)
              strcat(ret, tmp + 1);
            else
              strcat(ret, filename_im);
          }
          break;
        case 'w':
          snprintf(buf, sizeof(buf), "%d", gib_imlib_image_get_width(im));
          strcat(ret, buf);
          break;
        case 'h':
          snprintf(buf, sizeof(buf), "%d", gib_imlib_image_get_height(im));
          strcat(ret, buf);
          break;
        case 's':
          if (filename_im) {
            if (!stat(filename_im, &st)) {
              int size;

              size = st.st_size;
              snprintf(buf, sizeof(buf), "%d", size);
              strcat(ret, buf);
            } else
              strcat(ret, "[err]");
          }
          break;
        case 'p':
          snprintf(buf, sizeof(buf), "%d",
                   gib_imlib_image_get_width(im) *
                   gib_imlib_image_get_height(im));
          strcat(ret, buf);
          break;
        case 't':
          strcat(ret, gib_imlib_image_format(im));
          break;
        case '$':
          strcat(ret, "$");
          break;
        default:
          strncat(ret, c, 1);
          break;
      }
    } else if (*c == '\\') {
      c++;
      switch (*c) {
        case 'n':
          if (filename_im)
            strcat(ret, "\n");
          break;
        default:
          strncat(ret, c, 1);
          break;
      }
    } else
      strncat(ret, c, 1);
  }
  return gib_estrdup(ret);
}
Example #11
0
File: main.c Project: braneed/scrot
int
main(int argc,
     char **argv)
{
  Imlib_Image image;
  Imlib_Image thumbnail;
  Imlib_Load_Error err;
  char *filename_im = NULL, *filename_thumb = NULL;

  time_t t;
  struct tm *tm;

  init_parse_options(argc, argv);

  init_x_and_imlib(NULL, 0);

  if (!opt.output_file) {
    opt.output_file = gib_estrdup("%Y-%m-%d-%H%M%S_$wx$h_scrot.png");
    opt.thumb_file = gib_estrdup("%Y-%m-%d-%H%M%S_$wx$h_scrot-thumb.png");
  }


  if (opt.focused)
    image = scrot_grab_focused();
  else if (opt.window)
    image = scrot_grab_window();
  else if (opt.select)
    image = scrot_sel_and_grab_image();
  else {
    scrot_do_delay();
    if (opt.multidisp) {
      image = scrot_grab_shot_multi();
    } else {
      image = scrot_grab_shot();
    }
  }

  if (!image)
    gib_eprintf("no image grabbed");

  time(&t); /* Get the time directly after the screenshot */
  tm = localtime(&t);

  imlib_context_set_image(image);
  imlib_image_attach_data_value("quality", NULL, opt.quality, NULL);

  filename_im = im_printf(opt.output_file, tm, NULL, NULL, image);
  gib_imlib_save_image_with_error_return(image, filename_im, &err);
  if (err)
    gib_eprintf("Saving to file %s failed\n", filename_im);
  if (opt.thumb)
  {
    int cwidth, cheight;
    int twidth, theight;

    cwidth = gib_imlib_image_get_width(image);
    cheight = gib_imlib_image_get_height(image);

    /* Geometry based thumb size */
    if (opt.thumb_width || opt.thumb_height)
    {
      if (!opt.thumb_width)
      {
        twidth = cwidth * opt.thumb_height / cheight;
        theight = opt.thumb_height;
      }
      else if (!opt.thumb_height)
      {
        twidth = opt.thumb_width;
        theight = cheight * opt.thumb_width / cwidth;
      }
      else
      {
        twidth = opt.thumb_width;
        theight = opt.thumb_height;
      }
    }
    else
    {
      twidth = cwidth * opt.thumb / 100;
      theight = cheight * opt.thumb / 100;
    }

    thumbnail =
      gib_imlib_create_cropped_scaled_image(image, 0, 0, cwidth, cheight,
                                            twidth, theight, 1);
    if (thumbnail == NULL)
      gib_eprintf("Unable to create scaled Image\n");
    else
    {
      filename_thumb = im_printf(opt.thumb_file, tm, NULL, NULL, thumbnail);
      gib_imlib_save_image_with_error_return(thumbnail, filename_thumb, &err);
      if (err)
        gib_eprintf("Saving thumbnail %s failed\n", filename_thumb);
    }
  }
  if (opt.exec)
    scrot_exec_app(image, tm, filename_im, filename_thumb);
  gib_imlib_free_image_and_decache(image);

  return 0;
}
Example #12
0
void slideshow_change_image(winwidget winwid, int change, int render)
{
	gib_list *last = NULL;
	int i = 0;
	int jmp = 1;
	/* We can't use filelist_len in the for loop, since that changes when we
	 * encounter invalid images.
	 */
	int our_filelist_len = filelist_len;
	char *s;

	unsigned char tmode =0;
	int tim_x =0;
	int tim_y =0;
	double tzoom =0;

	/* Without this, clicking a one-image slideshow reloads it. Not very *
	   intelligent behaviour :-) */
	if (filelist_len < 2 && opt.cycle_once == 0)
		return;

	/* Ok. I do this in such an odd way to ensure that if the last or first *
	   image is not loadable, it will go through in the right direction to *
	   find the correct one. Otherwise SLIDE_LAST would try the last file, *
	   then loop forward to find a loadable one. */
	if (change == SLIDE_FIRST) {
		current_file = gib_list_last(filelist);
		change = SLIDE_NEXT;
	} else if (change == SLIDE_LAST) {
		current_file = filelist;
		change = SLIDE_PREV;
	}

	/* The for loop prevents us looping infinitely */
	for (i = 0; i < our_filelist_len; i++) {
		winwidget_free_image(winwid);
		switch (change) {
		case SLIDE_NEXT:
			current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
			break;
		case SLIDE_PREV:
			current_file = feh_list_jump(filelist, current_file, BACK, 1);
			break;
		case SLIDE_RAND:
			if (filelist_len > 1) {
				current_file = feh_list_jump(filelist, current_file, FORWARD,
					(rand() % (filelist_len - 1)) + 1);
				change = SLIDE_NEXT;
			}
			break;
		case SLIDE_JUMP_FWD:
			if (filelist_len < 5)
				jmp = 1;
			else if (filelist_len < 40)
				jmp = 2;
			else
				jmp = filelist_len / 20;
			if (!jmp)
				jmp = 2;
			current_file = feh_list_jump(filelist, current_file, FORWARD, jmp);
			/* important. if the load fails, we only want to step on ONCE to
			   try the next file, not another jmp */
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_BACK:
			if (filelist_len < 5)
				jmp = 1;
			else if (filelist_len < 40)
				jmp = 2;
			else
				jmp = filelist_len / 20;
			if (!jmp)
				jmp = 2;
			current_file = feh_list_jump(filelist, current_file, BACK, jmp);
			/* important. if the load fails, we only want to step back ONCE to
			   try the previous file, not another jmp */
			change = SLIDE_NEXT;
			break;
		default:
			eprintf("BUG!\n");
			break;
		}

		if (last) {
			filelist = feh_file_remove_from_list(filelist, last);
			last = NULL;
		}

		if (opt.keep_zoom_vp) {
		/* pre loadimage - record settings */
			tmode = winwid->mode;
			tim_x = winwid->im_x;
			tim_y = winwid->im_y;
			tzoom = winwid->zoom;
		}

		if ((winwidget_loadimage(winwid, FEH_FILE(current_file->data)))
		    != 0) {
			winwid->mode = MODE_NORMAL;
			winwid->file = current_file;
			if ((winwid->im_w != gib_imlib_image_get_width(winwid->im))
			    || (winwid->im_h != gib_imlib_image_get_height(winwid->im)))
				winwid->had_resize = 1;
			winwidget_reset_image(winwid);
			winwid->im_w = gib_imlib_image_get_width(winwid->im);
			winwid->im_h = gib_imlib_image_get_height(winwid->im);
			if (opt.keep_zoom_vp) {
				/* put back in: */
				winwid->mode = tmode;
				winwid->im_x = tim_x;
				winwid->im_y = tim_y;
				winwid->zoom = tzoom;
			}
			if (render) {
				if (opt.keep_zoom_vp) {
					winwidget_render_image(winwid, 0, 0);
				} else {
					winwidget_render_image(winwid, 1, 0);
				}
			}

			s = slideshow_create_name(FEH_FILE(current_file->data), winwid);
			winwidget_rename(winwid, s);
			free(s);

			break;
		} else
			last = current_file;
	}
	if (last)
		filelist = feh_file_remove_from_list(filelist, last);

	if (filelist_len == 0)
		eprintf("No more slides in show");

	if (opt.slideshow_delay > 0.0)
		feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, "SLIDE_CHANGE");
	return;
}
Example #13
0
void feh_reload_image(winwidget w, int resize, int force_new)
{
	char *title, *new_title;
	int len;
	Imlib_Image tmp;
	int old_w, old_h;

	unsigned char tmode =0;
	int tim_x =0;
	int tim_y =0;
	double tzoom =0;

	tmode = w->mode;
	tim_x = w->im_x;
	tim_y = w->im_y;
	tzoom = w->zoom;

	if (!w->file) {
		im_weprintf(w, "couldn't reload, this image has no file associated with it.");
		winwidget_render_image(w, 0, 0);
		return;
	}

	D(("resize %d, force_new %d\n", resize, force_new));

	free(FEH_FILE(w->file->data)->caption);
	FEH_FILE(w->file->data)->caption = NULL;

	len = strlen(w->name) + sizeof("Reloading: ") + 1;
	new_title = emalloc(len);
	snprintf(new_title, len, "Reloading: %s", w->name);
	title = estrdup(w->name);
	winwidget_rename(w, new_title);

	old_w = gib_imlib_image_get_width(w->im);
	old_h = gib_imlib_image_get_height(w->im);

	/*
	 * If we don't free the old image before loading the new one, Imlib2's
	 * caching will get in our way.
	 * However, if --reload is used (force_new == 0), we want to continue if
	 * the new image cannot be loaded, so we must not free the old image yet.
	 */
	if (force_new)
		winwidget_free_image(w);

	if ((feh_load_image(&tmp, FEH_FILE(w->file->data))) == 0) {
		if (force_new)
			eprintf("failed to reload image\n");
		else {
			im_weprintf(w, "Couldn't reload image. Is it still there?");
			winwidget_render_image(w, 0, 0);
		}
		winwidget_rename(w, title);
		free(title);
		free(new_title);
		return;
	}

	if (!resize && ((old_w != gib_imlib_image_get_width(tmp)) ||
			(old_h != gib_imlib_image_get_height(tmp))))
		resize = 1;

	if (!force_new)
		winwidget_free_image(w);

	w->im = tmp;
	winwidget_reset_image(w);

	w->mode = MODE_NORMAL;
	if ((w->im_w != gib_imlib_image_get_width(w->im))
	    || (w->im_h != gib_imlib_image_get_height(w->im)))
		w->had_resize = 1;
	if (w->has_rotated) {
		Imlib_Image temp;

		temp = gib_imlib_create_rotated_image(w->im, 0.0);
		w->im_w = gib_imlib_image_get_width(temp);
		w->im_h = gib_imlib_image_get_height(temp);
		gib_imlib_free_image_and_decache(temp);
	} else {
		w->im_w = gib_imlib_image_get_width(w->im);
		w->im_h = gib_imlib_image_get_height(w->im);
	}
	if (opt.keep_zoom_vp) {
		/* put back in: */
		w->mode = tmode;
		w->im_x = tim_x;
		w->im_y = tim_y;
		w->zoom = tzoom;
		winwidget_render_image(w, 0, 0);
	} else {
		winwidget_render_image(w, resize, 0);
	}

	winwidget_rename(w, title);
	free(title);
	free(new_title);

	return;
}
Example #14
0
File: slideshow.c Project: derf/feh
void slideshow_change_image(winwidget winwid, int change, int render)
{
	gib_list *last = NULL;
	gib_list *previous_file = current_file;
	int i = 0;
	int jmp = 1;
	/* We can't use filelist_len in the for loop, since that changes when we
	 * encounter invalid images.
	 */
	int our_filelist_len = filelist_len;

	if (opt.slideshow_delay > 0.0)
		feh_add_timer(cb_slide_timer, winwid, opt.slideshow_delay, "SLIDE_CHANGE");

	/* Without this, clicking a one-image slideshow reloads it. Not very *
	   intelligent behaviour :-) */
	if (filelist_len < 2 && opt.on_last_slide != ON_LAST_SLIDE_QUIT)
		return;

	/* Ok. I do this in such an odd way to ensure that if the last or first *
	   image is not loadable, it will go through in the right direction to *
	   find the correct one. Otherwise SLIDE_LAST would try the last file, *
	   then loop forward to find a loadable one. */
	if (change == SLIDE_FIRST) {
		current_file = gib_list_last(filelist);
		change = SLIDE_NEXT;
		previous_file = NULL;
	} else if (change == SLIDE_LAST) {
		current_file = filelist;
		change = SLIDE_PREV;
		previous_file = NULL;
	}

	/* The for loop prevents us looping infinitely */
	for (i = 0; i < our_filelist_len; i++) {
		winwidget_free_image(winwid);
		switch (change) {
		case SLIDE_NEXT:
			current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
			break;
		case SLIDE_PREV:
			current_file = feh_list_jump(filelist, current_file, BACK, 1);
			break;
		case SLIDE_RAND:
			if (filelist_len > 1) {
				current_file = feh_list_jump(filelist, current_file, FORWARD,
					(random() % (filelist_len - 1)) + 1);
				change = SLIDE_NEXT;
			}
			break;
		case SLIDE_JUMP_FWD:
			if (filelist_len < 5)
				jmp = 1;
			else if (filelist_len < 40)
				jmp = 2;
			else
				jmp = filelist_len / 20;
			if (!jmp)
				jmp = 2;
			current_file = feh_list_jump(filelist, current_file, FORWARD, jmp);
			/* important. if the load fails, we only want to step on ONCE to
			   try the next file, not another jmp */
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_BACK:
			if (filelist_len < 5)
				jmp = 1;
			else if (filelist_len < 40)
				jmp = 2;
			else
				jmp = filelist_len / 20;
			if (!jmp)
				jmp = 2;
			current_file = feh_list_jump(filelist, current_file, BACK, jmp);
			/* important. if the load fails, we only want to step back ONCE to
			   try the previous file, not another jmp */
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_NEXT_DIR:
			{
				char old_dir[PATH_MAX], new_dir[PATH_MAX];
				int j;

				feh_file_dirname(old_dir, FEH_FILE(current_file->data), PATH_MAX);

				for (j = 0; j < our_filelist_len; j++) {
					current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
					feh_file_dirname(new_dir, FEH_FILE(current_file->data), PATH_MAX);
					if (strcmp(old_dir, new_dir) != 0)
						break;
				}
			}
			change = SLIDE_NEXT;
			break;
		case SLIDE_JUMP_PREV_DIR:
			{
				char old_dir[PATH_MAX], new_dir[PATH_MAX];
				int j;

				/* Start the search from the previous file in case we are on
				   the first file of a directory */
				current_file = feh_list_jump(filelist, current_file, BACK, 1);
				feh_file_dirname(old_dir, FEH_FILE(current_file->data), PATH_MAX);

				for (j = 0; j < our_filelist_len; j++) {
					current_file = feh_list_jump(filelist, current_file, BACK, 1);
					feh_file_dirname(new_dir, FEH_FILE(current_file->data), PATH_MAX);
					if (strcmp(old_dir, new_dir) != 0)
						break;
				}

				/* Next file is the first entry of prev_dir */
				current_file = feh_list_jump(filelist, current_file, FORWARD, 1);
			}
			change = SLIDE_NEXT;
			break;
		default:
			eprintf("BUG!\n");
			break;
		}

		if (last) {
			filelist = feh_file_remove_from_list(filelist, last);
			last = NULL;
		}

		if (opt.on_last_slide == ON_LAST_SLIDE_HOLD && previous_file &&
			((current_file == filelist && change == SLIDE_NEXT) ||
			(previous_file == filelist && change == SLIDE_PREV))) {
				current_file = previous_file;
		}

		if (winwidget_loadimage(winwid, FEH_FILE(current_file->data))) {
			int w = gib_imlib_image_get_width(winwid->im);
			int h = gib_imlib_image_get_height(winwid->im);
			if (feh_should_ignore_image(winwid->im)) {
				last = current_file;
				continue;
			}
			winwid->mode = MODE_NORMAL;
			winwid->file = current_file;
			if ((winwid->im_w != w) || (winwid->im_h != h))
				winwid->had_resize = 1;
			winwidget_reset_image(winwid);
			winwid->im_w = w;
			winwid->im_h = h;
			if (render) {
				winwidget_render_image(winwid, 1, 0);
			}
			break;
		} else
			last = current_file;
	}
	if (last)
		filelist = feh_file_remove_from_list(filelist, last);

	if (filelist_len == 0)
		eprintf("No more slides in show");

	return;
}
Example #15
0
int feh_file_info_load(feh_file * file, Imlib_Image im)
{
	struct stat st;
	int need_free = 1;
	Imlib_Image im1;

	D(4, ("im is %p\n", im));

	if (im)
		need_free = 0;

	errno = 0;
	if (stat(file->filename, &st)) {
		/* Display useful error message */
		switch (errno) {
		case ENOENT:
		case ENOTDIR:
			if (!opt.quiet)
				weprintf("%s does not exist - skipping", file->filename);
			break;
		case ELOOP:
			if (!opt.quiet)
				weprintf("%s - too many levels of symbolic links - skipping", file->filename);
			break;
		case EACCES:
			if (!opt.quiet)
				weprintf("you don't have permission to open %s - skipping", file->filename);
			break;
		default:
			if (!opt.quiet)
				weprintf("couldn't open %s ", file->filename);
			break;
		}
		return(1);
	}

	if (im)
		im1 = im;
	else if (!feh_load_image(&im1, file))
		return(1);

	if (!im1)
		return(1);

	file->info = feh_file_info_new();

	file->info->width = gib_imlib_image_get_width(im1);
	file->info->height = gib_imlib_image_get_height(im1);

	file->info->has_alpha = gib_imlib_image_has_alpha(im1);

	file->info->pixels = file->info->width * file->info->height;

	file->info->format = estrdup(gib_imlib_image_format(im1));

	file->info->size = st.st_size;

	if (need_free && im1)
		gib_imlib_free_image_and_decache(im1);
	return(0);
}
Example #16
0
File: menu.c Project: talisein/feh
void feh_menu_draw_item(feh_menu_item * i, Imlib_Image im, int ox, int oy)
{
	D(("drawing item %p (text %s)\n", i, i->text));

	if (i->text) {
		D(("text item\n"));
		if (MENU_ITEM_IS_SELECTED(i)) {
			D(("selected item\n"));
			/* draw selected image */
			feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 1);
		} else {
			D(("unselected item\n"));
			/* draw unselected image */
			feh_menu_item_draw_at(i->x, i->y, i->w, i->h, im, ox, oy, 0);
		}

		/* draw text */
		gib_imlib_text_draw(im, opt.menu_fn, opt.menu_style_l,
				i->x - ox + i->text_x, i->y - oy + FEH_MENUITEM_PAD_TOP,
				i->text, IMLIB_TEXT_TO_RIGHT, 0, 0, 0, 255);
		if (i->icon) {
			Imlib_Image im2;

			D(("icon item\n"));

			im2 = i->icon;
			if (im2) {
				int iw, ih, ow, oh;

				iw = gib_imlib_image_get_width(im2);
				ih = gib_imlib_image_get_height(im2);
				if (ih <= (i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM)) {
					ow = iw;
					oh = ih;
				} else {
					ow = (iw * (i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM)) / ih;
					oh = i->h - FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM;
				}
				gib_imlib_blend_image_onto_image(im, im2,
								 0, 0, 0,
								 iw, ih,
								 i->x +
								 i->icon_x -
								 ox,
								 i->y +
								 FEH_MENUITEM_PAD_TOP
								 +
								 (((i->h -
								    FEH_MENUITEM_PAD_TOP - FEH_MENUITEM_PAD_BOTTOM)
								   - oh) / 2) - oy, ow, oh, 1, 1, 1);
				gib_imlib_free_image(im2);
			}
		}
		if (i->submenu) {
			D(("submenu item\n"));
			feh_menu_draw_submenu_at(i->x + i->sub_x,
						 i->y +
						 FEH_MENUITEM_PAD_TOP +
						 ((i->h -
						   FEH_MENUITEM_PAD_TOP -
						   FEH_MENUITEM_PAD_BOTTOM
						   -
						   FEH_MENU_SUBMENU_H) /
						  2), im, ox, oy);
		}
		if (i->is_toggle) {
			D(("toggleable item\n"));
			feh_menu_draw_toggle_at(i->x + i->toggle_x,
						i->y +
						FEH_MENUITEM_PAD_TOP +
						((i->h -
						  FEH_MENUITEM_PAD_TOP -
						  FEH_MENUITEM_PAD_BOTTOM -
						  FEH_MENU_TOGGLE_H) / 2),
						FEH_MENU_TOGGLE_W, FEH_MENU_TOGGLE_H, im, ox, oy, MENU_ITEM_IS_ON(i));
		}
	} else {
		D(("separator item\n"));
		feh_menu_draw_separator_at(i->x, i->y, i->w, i->h, im, ox, oy);
	}
	return;
}
Example #17
0
File: menu.c Project: talisein/feh
void feh_menu_calc_size(feh_menu * m)
{
	int prev_w, prev_h;
	feh_menu_item *i;
	int j = 0, count = 0, max_w = 0, max_h = 0, icon_w = 0, next_w = 0;
	int toggle_w = 0;

	prev_w = m->w;
	prev_h = m->h;
	m->calc = 0;

	for (i = m->items; i; i = i->next) {
		int w, h;

		feh_menu_entry_get_size(m, i, &w, &h);
		if (w > max_w)
			max_w = w;
		if (h > max_h)
			max_h = h;
		if (i->submenu) {
			next_w = FEH_MENU_SUBMENU_W;
			if (FEH_MENU_SUBMENU_H > max_h)
				max_h = FEH_MENU_SUBMENU_H;
		}
		if (i->is_toggle) {
			toggle_w = FEH_MENU_TOGGLE_W + FEH_MENU_TOGGLE_PAD;
			if (FEH_MENU_TOGGLE_H > max_h)
				max_h = FEH_MENU_TOGGLE_H;
		}
		count++;
	}

	for (i = m->items; i; i = i->next) {
		if (i->icon) {
			Imlib_Image im;

			im = i->icon;
			if (im) {
				int iw, ih, ow, oh;

				iw = gib_imlib_image_get_width(im);
				ih = gib_imlib_image_get_height(im);
				if (ih <= max_h) {
					ow = iw;
					oh = ih;
				} else {
					ow = (iw * max_h) / ih;
					oh = max_h;
				}
				if (ow > icon_w)
					icon_w = ow;
			}
		}
	}
	m->h = FEH_MENU_PAD_TOP;
	for (i = m->items; i; i = i->next) {
		i->x = FEH_MENU_PAD_LEFT;
		i->y = m->h;
		i->w = max_w + icon_w + toggle_w + next_w;
		i->icon_x = FEH_MENUITEM_PAD_LEFT;
		i->toggle_x = i->icon_x + icon_w;
		i->text_x = i->toggle_x + toggle_w;
		i->sub_x = i->text_x + max_w;
		if (i->text)
			i->h = max_h;
		else
			i->h = FEH_MENU_SEP_MAX_H;
		m->h += i->h;
		j++;
	}
	m->h += FEH_MENU_PAD_BOTTOM;
	m->w = next_w + toggle_w + icon_w + max_w + FEH_MENU_PAD_LEFT + FEH_MENU_PAD_RIGHT;

	if ((prev_w != m->w) || (prev_h != m->h)) {
		if (m->pmap)
			XFreePixmap(disp, m->pmap);
		m->pmap = 0;
		m->needs_redraw = 1;
		XResizeWindow(disp, m->win, m->w, m->h);
		m->updates = imlib_update_append_rect(m->updates, 0, 0, m->w, m->h);
	}
	D(("menu size calculated. w=%d h=%d\n", m->w, m->h));

	/* Make sure bg is same size */
	if (m->bg) {
		int bg_w, bg_h;

		bg_w = gib_imlib_image_get_width(m->bg);
		bg_h = gib_imlib_image_get_height(m->bg);

		if (m->w != bg_w || m->h != bg_h) {
			Imlib_Image newim = imlib_create_image(m->w, m->h);

			D(("resizing bg to %dx%d\n", m->w, m->h));

			gib_imlib_blend_image_onto_image(newim, m->bg, 0, 0, 0, bg_w, bg_h, 0, 0, m->w, m->h, 0, 0, 1);
			gib_imlib_free_image_and_decache(m->bg);
			m->bg = newim;
		}
	}

	return;
}
Example #18
0
File: menu.c Project: talisein/feh
void feh_menu_cb(feh_menu * m, feh_menu_item * i, int action, void *data)
{
	char *path;
	Imlib_Image im;
	winwidget winwid;

	switch (action) {
		case CB_BG_TILED:
			path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename);
			feh_wm_set_bg(path, m->fehwin->im, 0, 0, 0, (int) data, 1);
			free(path);
			break;
		case CB_BG_SCALED:
			path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename);
			feh_wm_set_bg(path, m->fehwin->im, 0, 1, 0, (int) data, 1);
			free(path);
			break;
		case CB_BG_CENTERED:
			path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename);
			feh_wm_set_bg(path, m->fehwin->im, 1, 0, 0, (int) data, 1);
			free(path);
			break;
		case CB_BG_FILLED:
			path = feh_absolute_path(FEH_FILE(m->fehwin->file->data)->filename);
			feh_wm_set_bg(path, m->fehwin->im, 0, 0, 1, (int) data, 1);
			free(path);
			break;
		case CB_BG_TILED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 0, (int) data, 1);
			break;
		case CB_BG_SCALED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 1, 0, (int) data, 1);
			break;
		case CB_BG_CENTERED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 1, 0, 0, (int) data, 1);
			break;
		case CB_BG_FILLED_NOFILE:
			feh_wm_set_bg(NULL, m->fehwin->im, 0, 0, 1, (int) data, 1);
			break;
		case CB_ABOUT:
			if (feh_load_image_char(&im, PREFIX "/share/feh/images/about.png")
					!= 0) {
				winwid = winwidget_create_from_image(im, "About " PACKAGE,
						WIN_TYPE_ABOUT);
				winwid->file = gib_list_add_front(NULL,
						feh_file_new(PREFIX "/share/feh/images/about.png"));
				winwidget_show(winwid);
			}
			break;
		case CB_CLOSE:
			winwidget_destroy(m->fehwin);
			break;
		case CB_EXIT:
			winwidget_destroy_all();
			break;
		case CB_RESET:
			if (m->fehwin->has_rotated) {
				m->fehwin->im_w = gib_imlib_image_get_width(m->fehwin->im);
				m->fehwin->im_h = gib_imlib_image_get_height(m->fehwin->im);
				winwidget_resize(m->fehwin, m->fehwin->im_w, m->fehwin->im_h);
			}
			winwidget_reset_image(m->fehwin);
			winwidget_render_image(m->fehwin, 1, 1);
			break;
		case CB_RELOAD:
			feh_reload_image(m->fehwin, 0, 0);
			break;
		case CB_REMOVE:
			feh_filelist_image_remove(m->fehwin, 0);
			break;
		case CB_DELETE:
			feh_filelist_image_remove(m->fehwin, 1);
			break;
		case CB_REMOVE_THUMB:
			feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 0);
			feh_filelist_image_remove(m->fehwin, 0);
			break;
		case CB_DELETE_THUMB:
			feh_thumbnail_mark_removed(FEH_FILE(m->fehwin->file->data), 1);
			feh_filelist_image_remove(m->fehwin, 1);
			break;
		case CB_SORT_FILENAME:
			filelist = gib_list_sort(filelist, feh_cmp_filename);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST);
			}
			break;
		case CB_SORT_IMAGENAME:
			filelist = gib_list_sort(filelist, feh_cmp_name);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST);
			}
			break;
		case CB_SORT_FILESIZE:
			filelist = gib_list_sort(filelist, feh_cmp_size);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST);
			}
			break;
		case CB_SORT_RANDOMIZE:
			filelist = gib_list_randomize(filelist);
			if (opt.jump_on_resort) {
				slideshow_change_image(m->fehwin, SLIDE_FIRST);
			}
			break;
		case CB_FIT:
			winwidget_size_to_image(m->fehwin);
			break;
		case CB_EDIT_ROTATE:
			feh_edit_inplace_orient(m->fehwin, (int) data);
			break;
		case CB_SAVE_IMAGE:
			slideshow_save_image(m->fehwin);
			break;
		case CB_SAVE_FILELIST:
			feh_save_filelist();
			break;
		case CB_OPT_DRAW_FILENAME:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.draw_filename = TRUE;
			else
				opt.draw_filename = FALSE;
			winwidget_rerender_all(0, 1);
			break;
		case CB_OPT_DRAW_ACTIONS:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.draw_actions = TRUE;
			else
				opt.draw_actions = FALSE;
			winwidget_rerender_all(0, 1);
			break;
		case CB_OPT_KEEP_HTTP:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.keep_http = TRUE;
			else
				opt.keep_http = FALSE;
			break;
		case CB_OPT_FREEZE_WINDOW:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i)) {
				opt.geom_flags = (WidthValue | HeightValue);
				opt.geom_w = m->fehwin->w;
				opt.geom_h = m->fehwin->h;
			} else {
				opt.geom_flags = 0;
			}
			break;
		case CB_OPT_FULLSCREEN:
			feh_menu_cb_opt_fullscreen(m, i);
			break;
		case CB_OPT_AUTO_ZOOM:
			MENU_ITEM_TOGGLE(i);
			if (MENU_ITEM_IS_ON(i))
				opt.zoom_mode = ZOOM_MODE_FILL;
			else
				opt.zoom_mode = 0;
			winwidget_rerender_all(1, 1);
			break;
	}
	return;
}
Example #19
0
void init_collage_mode(void)
{
	Imlib_Image im_main;
	Imlib_Image im_temp;
	int ww, hh, www, hhh, xxx, yyy;
	int w = 800, h = 600;
	int bg_w = 0, bg_h = 0;
	winwidget winwid = NULL;
	Imlib_Image bg_im = NULL, im_thumb = NULL;
	feh_file *file = NULL;
	unsigned char trans_bg = 0;
	gib_list *l, *last = NULL;
	char *s;

	D_ENTER(4);

	mode = "collage";

	/* Use bg image dimensions for default size */
	if (opt.bg && opt.bg_file) {
		if (!strcmp(opt.bg_file, "trans"))
			trans_bg = 1;
		else {

			D(4, ("Time to apply a background to blend onto\n"));
			if (feh_load_image_char(&bg_im, opt.bg_file) != 0) {
				bg_w = gib_imlib_image_get_width(bg_im);
				bg_h = gib_imlib_image_get_height(bg_im);
			}
		}
	}

	if (!opt.limit_w || !opt.limit_h) {
		if (bg_im) {
			if (opt.verbose)
				fprintf(stdout,
					PACKAGE
					" - No size restriction specified for collage.\n"
					" You did specify a background however, so the\n"
					" collage size has defaulted to the size of the image\n");
			opt.limit_w = bg_w;
			opt.limit_h = bg_h;
		} else {
			if (opt.verbose)
				fprintf(stdout,
					PACKAGE
					" - No size restriction specified for collage.\n"
					" - For collage mode, you need to specify width and height.\n"
					" Using defaults (width 800, height 600)\n");
			opt.limit_w = 800;
			opt.limit_h = 600;
		}
	}

	w = opt.limit_w;
	h = opt.limit_h;
	D(4, ("Limiting width to %d and height to %d\n", w, h));

	im_main = imlib_create_image(w, h);

	if (!im_main)
		eprintf("Imlib error creating image");

	if (bg_im)
		gib_imlib_blend_image_onto_image(im_main, bg_im,
				gib_imlib_image_has_alpha(bg_im), 0, 0,
				bg_w, bg_h, 0, 0, w, h, 1, 0, 0);
	else if (trans_bg) {
		gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h, 0, 0, 0, 0);
		gib_imlib_image_set_has_alpha(im_main, 1);
	} else {
		/* Colour the background */
		gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h, 0, 0, 0, 255);
	}

	/* Create the title string */

	if (!opt.title)
		s = estrdup(PACKAGE " [collage mode]");
	else
		s = estrdup(feh_printf(opt.title, NULL));

	if (opt.display) {
		winwid = winwidget_create_from_image(im_main, s, WIN_TYPE_SINGLE);
		winwidget_show(winwid);
	}

	for (l = filelist; l; l = l->next) {
		file = FEH_FILE(l->data);
		if (last) {
			filelist = feh_file_remove_from_list(filelist, last);
			filelist_len--;
			last = NULL;
		}
		D(3, ("About to load image %s\n", file->filename));
		if (feh_load_image(&im_temp, file) != 0) {
			D(3, ("Successfully loaded %s\n", file->filename));
			if (opt.verbose)
				feh_display_status('.');
			www = opt.thumb_w;
			hhh = opt.thumb_h;
			ww = gib_imlib_image_get_width(im_temp);
			hh = gib_imlib_image_get_height(im_temp);

			if (opt.aspect) {
				double ratio = 0.0;

				/* Keep the aspect ratio for the thumbnail */
				ratio = ((double) ww / hh) / ((double) www / hhh);

				if (ratio > 1.0)
					hhh = opt.thumb_h / ratio;
				else if (ratio != 1.0)
					www = opt.thumb_w * ratio;
			}

			if ((!opt.stretch) && ((www > ww) || (hhh > hh))) {
				/* Don't make the image larger unless stretch is specified */
				www = ww;
				hhh = hh;
			}

			/* pick random coords for thumbnail */
			xxx = ((w - www) * ((double) rand() / RAND_MAX));
			yyy = ((h - hhh) * ((double) rand() / RAND_MAX));
			D(5, ("image going on at x=%d, y=%d\n", xxx, yyy));

			im_thumb = gib_imlib_create_cropped_scaled_image(im_temp,
					0, 0, ww, hh, www, hhh, 1);
			gib_imlib_free_image_and_decache(im_temp);

			if (opt.alpha) {
				DATA8 atab[256];

				D(4, ("Applying alpha options\n"));
				gib_imlib_image_set_has_alpha(im_thumb, 1);
				memset(atab, opt.alpha_level, sizeof(atab));
				gib_imlib_apply_color_modifier_to_rectangle(im_thumb,
						0, 0, www, hhh, NULL, NULL, NULL, atab);
			}
			gib_imlib_blend_image_onto_image(im_main, im_thumb,
					gib_imlib_image_has_alpha(im_thumb), 0, 0, www, hhh, xxx,
					yyy,www, hhh, 1, gib_imlib_image_has_alpha(im_thumb), 0);
			gib_imlib_free_image_and_decache(im_thumb);
		} else {
			last = l;
			if (opt.verbose)
				feh_display_status('x');
		}
		if (opt.display) {
			winwidget_render_image(winwid, 0, 0);
			if (!feh_main_iteration(0))
				exit(0);
		}
	}
	if (opt.verbose)
		fprintf(stdout, "\n");

	if (opt.output && opt.output_file) {
		char output_buf[1024];
		if (opt.output_dir)
			snprintf(output_buf, 1024, "%s/%s", opt.output_dir, opt.output_file);
		else
			strncpy(output_buf, opt.output_file, 1024);
		gib_imlib_save_image(im_main, output_buf);
		if (opt.verbose) {
			int tw, th;

			tw = gib_imlib_image_get_width(im_main);
			th = gib_imlib_image_get_height(im_main);
			fprintf(stdout, PACKAGE " - File saved as %s\n", output_buf);
			fprintf(stdout,
				"    - Image is %dx%d pixels and contains %d thumbnails\n",
				tw, th, (tw / opt.thumb_w) * (th / opt.thumb_h));
		}
	}

	if (!opt.display)
		gib_imlib_free_image_and_decache(im_main);
	free(s);
	D_RETURN_(4);
}
Example #20
0
static void feh_event_handle_MotionNotify(XEvent * ev)
{
	winwidget winwid = NULL;
	int dx, dy;
	int scr_width, scr_height;

	scr_width = scr->width;
	scr_height = scr->height;
#ifdef HAVE_LIBXINERAMA
	if (opt.xinerama && xinerama_screens) {
		scr_width = xinerama_screens[xinerama_screen].width;
		scr_height = xinerama_screens[xinerama_screen].height;
	}
#endif				/* HAVE_LIBXINERAMA */

	if (menu_root) {
		feh_menu *m;
		feh_menu_item *selected_item, *mouseover_item;

		D(("motion notify with menus open\n"));
		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));

		if (ev->xmotion.window == menu_cover) {
			return;
		} else if ((m = feh_menu_get_from_window(ev->xmotion.window))) {
			selected_item = feh_menu_find_selected(m);
			mouseover_item = feh_menu_find_at_xy(m, ev->xmotion.x, ev->xmotion.y);

			if (selected_item != mouseover_item) {
				D(("selecting a menu item\n"));
				if (selected_item)
					feh_menu_deselect_selected(m);
				if ((mouseover_item)
						&& ((mouseover_item->action)
							|| (mouseover_item->submenu)
							|| (mouseover_item->func_gen_sub)))
					feh_menu_select(m, mouseover_item);
			}
			/* check if we are close to the right and/or the bottom edge of the
			 * screen. If so, and if the menu we are currently over is partially
			 * hidden, slide the menu to the left and/or up until it is
			 * fully visible */

			/* FIXME: get this working nicely with xinerama screen edges --
			 * at the moment it does really funky stuff with
			 * scr_{width,height} instead of scr->{width,height} -- pabs*/
			if (mouseover_item
					&& ((scr->width - (ev->xmotion.x + m->x)) <
						m->w || (scr->height - (ev->xmotion.y + m->y)) < m->w)) {
				dx = scr_width - (m->x + m->w);
				dy = scr_height - (m->y + m->h);
				dx = dx < 0 ? dx : 0;
				dy = dy < 0 ? dy : 0;
				if (dx || dy)
					feh_menu_slide_all_menus_relative(dx, dy);
			}
			/* if a submenu is open we want to see that also */
			if (mouseover_item && m->next && ((scr->width - (ev->xmotion.x + m->next->x))
						< m->next->w
						|| (scr->height -
							(ev->xmotion.y + m->next->y)) < m->next->w)) {
				dx = scr->width - (m->next->x + m->next->w);
				dy = scr->height - (m->next->y + m->next->h);
				dx = dx < 0 ? dx : 0;
				dy = dy < 0 ? dy : 0;
				if (dx || dy)
					feh_menu_slide_all_menus_relative(dx, dy);
			}
		}
	} else if (opt.mode == MODE_ZOOM) {
		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));

		winwid = winwidget_get_from_window(ev->xmotion.window);
		if (winwid) {
			if (ev->xmotion.x > winwid->click_offset_x)
				winwid->zoom = winwid->old_zoom + (
						((double) ev->xmotion.x - (double) winwid->click_offset_x)
						/ 128.0);
			else
				winwid->zoom = winwid->old_zoom - (
						((double) winwid->click_offset_x - (double) ev->xmotion.x)
						/ 128.0);

			if (winwid->zoom < ZOOM_MIN)
				winwid->zoom = ZOOM_MIN;
			else if (winwid->zoom > ZOOM_MAX)
				winwid->zoom = ZOOM_MAX;

			/* center around click_offset */
			winwid->im_x = winwid->click_offset_x
					- (winwid->im_click_offset_x * winwid->zoom);
			winwid->im_y = winwid->click_offset_y
					- (winwid->im_click_offset_y * winwid->zoom);

			winwidget_render_image(winwid, 0, 1);
		}
	} else if ((opt.mode == MODE_PAN) || (opt.mode == MODE_NEXT)) {
		int orig_x, orig_y;

		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));
		winwid = winwidget_get_from_window(ev->xmotion.window);
		if (winwid) {
			if (opt.mode == MODE_NEXT) {
				if ((abs(winwid->click_offset_x - (ev->xmotion.x - winwid->im_x)) > FEH_JITTER_OFFSET)
						|| (abs(winwid->click_offset_y - (ev->xmotion.y - winwid->im_y)) > FEH_JITTER_OFFSET)
						|| (time(NULL) - winwid->click_start_time > FEH_JITTER_TIME)) {
					opt.mode = MODE_PAN;
					winwid->mode = MODE_PAN;
				}
				else
					return;
			}
			D(("Panning\n"));
			orig_x = winwid->im_x;
			orig_y = winwid->im_y;

			winwid->im_x = ev->xmotion.x - winwid->click_offset_x;
			winwid->im_y = ev->xmotion.y - winwid->click_offset_y;

			winwidget_sanitise_offsets(winwid);

			D(("im_x %d, im_w %d, off %d, mx %d, my %d\n", winwid->im_x,
				winwid->im_w, winwid->click_offset_x, ev->xmotion.x,
				ev->xmotion.y));

			/* XWarpPointer generates a MotionNotify event which we will
			 * parse. Since that event would undo the effect of the pointer
			 * warp, we need to change the click_offset to compensate this.
			 */
			if ((winwid->w - ev->xmotion.x <= 1) && (winwid->im_x < 0))
			{
				XWarpPointer(disp, None, winwid->win, 0, 0, 0, 0, 3,
					ev->xmotion.y);
				winwid->click_offset_x -= winwid->w - 4;
			}
			// TODO needlessly warps for certain zoom levels
			else if ((ev->xmotion.x <= 1) && (winwid->im_x >
					(winwid->w - winwid->im_w * winwid->zoom)))
			{
				XWarpPointer(disp, None, winwid->win, 0, 0, 0, 0,
					winwid->w - 4, ev->xmotion.y);
				winwid->click_offset_x += winwid->w - 4;
			}
			else if ((winwid->h - ev->xmotion.y <= 1)
					&& (winwid->im_y < 0))
			{
				XWarpPointer(disp, None, winwid->win, 0, 0, 0, 0,
					ev->xmotion.x, 3);
				winwid->click_offset_y -= winwid->h - 4;
			}
			// TODO needlessly warps for certain zoomlevels
			else if ((ev->xmotion.y <= 1) && (winwid->im_y >
					(winwid->h - winwid->im_h * winwid->zoom)))
			{
				XWarpPointer(disp, None, winwid->win, 0, 0, 0, 0,
					ev->xmotion.x, winwid->h - 4);
				winwid->click_offset_y += winwid->h - 4;
			}

			if ((winwid->im_x != orig_x)
					|| (winwid->im_y != orig_y))
				winwidget_render_image(winwid, 0, 1);
		}
	} else if (opt.mode == MODE_ROTATE) {
		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));
		winwid = winwidget_get_from_window(ev->xmotion.window);
		if (winwid) {
			D(("Rotating\n"));
			if (!winwid->has_rotated) {
				Imlib_Image temp;

				temp = gib_imlib_create_rotated_image(winwid->im, 0.0);
				winwid->im_w = gib_imlib_image_get_width(temp);
				winwid->im_h = gib_imlib_image_get_height(temp);
				gib_imlib_free_image_and_decache(temp);
				if (!winwid->full_screen && !opt.geom_flags)
					winwidget_resize(winwid, winwid->im_w, winwid->im_h);
				winwid->has_rotated = 1;
			}
			winwid->im_angle = (ev->xmotion.x - winwid->w / 2) / ((double) winwid->w / 2) * 3.1415926535;
			D(("angle: %f\n", winwid->im_angle));
			winwidget_render_image(winwid, 0, 1);
		}
	} else if (opt.mode == MODE_BLUR) {
		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));
		winwid = winwidget_get_from_window(ev->xmotion.window);
		if (winwid) {
			Imlib_Image temp, ptr;
			signed int blur_radius;

			D(("Blurring\n"));

			temp = gib_imlib_clone_image(winwid->im);
			blur_radius = (((double) ev->xmotion.x / winwid->w) * 20) - 10;
			D(("angle: %d\n", blur_radius));
			if (blur_radius > 0)
				gib_imlib_image_sharpen(temp, blur_radius);
			else
				gib_imlib_image_blur(temp, 0 - blur_radius);
			ptr = winwid->im;
			winwid->im = temp;
			winwidget_render_image(winwid, 0, 1);
			gib_imlib_free_image_and_decache(winwid->im);
			winwid->im = ptr;
		}
	} else {
		while (XCheckTypedWindowEvent(disp, ev->xmotion.window, MotionNotify, ev));
		winwid = winwidget_get_from_window(ev->xmotion.window);
		if ((winwid != NULL) && (winwid->type == WIN_TYPE_THUMBNAIL)) {
			feh_thumbnail *thumbnail;
			int x, y;

			x = (ev->xbutton.x - winwid->im_x) / winwid->zoom;
			y = (ev->xbutton.y - winwid->im_y) / winwid->zoom;
			thumbnail = feh_thumbnail_get_thumbnail_from_coords(x, y);
			feh_thumbnail_select(winwid, thumbnail);
		}
	}
	return;
}