コード例 #1
0
ファイル: panel.c プロジェクト: ETroll/toaruos
static void toggle_hide_panel(void) {
	static int panel_hidden = 0;

	if (panel_hidden) {
		/* Unhide the panel */
		for (int i = PANEL_HEIGHT-1; i >= 0; i--) {
			yutani_window_move(yctx, panel, 0, -i);
			usleep(10000);
		}
		panel_hidden = 0;
	} else {
		/* Hide the panel */
		for (int i = 1; i <= PANEL_HEIGHT-1; i++) {
			yutani_window_move(yctx, panel, 0, -i);
			usleep(10000);
		}
		panel_hidden = 1;
	}
}
コード例 #2
0
ファイル: drawlines.c プロジェクト: ETroll/toaruos
int main (int argc, char ** argv) {
	left   = 100;
	top    = 100;
	width  = 500;
	height = 500;

	yctx = yutani_init();
	wina = yutani_window_create(yctx, width, height);
	yutani_window_move(yctx, wina, left, top);

	ctx = init_graphics_yutani(wina);
	draw_fill(ctx, rgb(0,0,0));

	pthread_t thread;
	pthread_create(&thread, NULL, draw_thread, NULL);

	while (!should_exit) {
		yutani_msg_t * m = yutani_poll(yctx);
		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
							should_exit = 1;
							syscall_yield();
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					should_exit = 1;
					break;
				default:
					break;
			}
		}
		free(m);
	}

	yutani_close(yctx, wina);

	return 0;
}
コード例 #3
0
ttk_window_t * ttk_window_new(char * title, uint16_t width, uint16_t height) {
	ttk_window_t * new_win = malloc(sizeof(ttk_window_t));
	new_win->title  = strdup(title);
	new_win->width  = width;
	new_win->height = height;
	new_win->off_x  = decor_left_width;
	new_win->off_y  = decor_top_height;

	new_win->core_window = yutani_window_create(yctx, new_win->width + decor_width(), new_win->height + decor_height());
	yutani_window_move(yctx, new_win->core_window, TTK_DEFAULT_X, TTK_DEFAULT_Y);
	assert(new_win->core_window && "Oh dear, I've failed to allocate a new window from the server. This is terrible.");

	/* XXX icon; also need to do this if we change the title later */
	yutani_window_advertise(yctx, new_win->core_window, new_win->title);

	new_win->core_context = init_graphics_yutani_double_buffer(new_win->core_window);
	draw_fill(new_win->core_context, rgb(TTK_BACKGROUND_DEFAULT));

	ttk_window_draw(new_win);

	hashmap_set(ttk_wids_to_windows, (void*)new_win->core_window->wid, new_win);
}
コード例 #4
0
ファイル: julia.c プロジェクト: mtnkdev/toaruos
int main(int argc, char * argv[]) {

	static struct option long_opts[] = {
		{"no-repeat", no_argument,    0, 'n'},
		{"initer", required_argument, 0, 'i'},
		{"minx",   required_argument, 0, 'x'},
		{"maxx",   required_argument, 0, 'X'},
		{"conx",   required_argument, 0, 'c'},
		{"cony",   required_argument, 0, 'C'},
		{"width",  required_argument, 0, 'W'},
		{"height", required_argument, 0, 'H'},
		{"help",   no_argument,       0, 'h'},
		{0,0,0,0}
	};

	if (argc > 1) {
		/* Read some arguments */
		int index, c;
		while ((c = getopt_long(argc, argv, "ni:x:X:c:C:W:H:h", long_opts, &index)) != -1) {
			if (!c) {
				if (long_opts[index].flag == 0) {
					c = long_opts[index].val;
				}
			}
			switch (c) {
				case 'n':
					no_repeat = 1;
					break;
				case 'i':
					initer = atof(optarg);
					break;
				case 'x':
					Minx = atof(optarg);
					break;
				case 'X':
					Maxx = atof(optarg);
					break;
				case 'c':
					conx = atof(optarg);
					break;
				case 'C':
					cony = atof(optarg);
					break;
				case 'W':
					width = atoi(optarg);
					break;
				case 'H':
					height = atoi(optarg);
					break;
				case 'h':
					usage(argv);
					exit(0);
					break;
				default:
					break;
			}
		}
	}

	yctx = yutani_init();
	init_decorations();

	window = yutani_window_create(yctx, width + decor_width(), height + decor_height());
	yutani_window_move(yctx, window, left, top);

	yutani_window_advertise_icon(yctx, window, "Julia Fractals", "julia");

	ctx = init_graphics_yutani(window);

	redraw();
	yutani_flip(yctx, window);

	int playing = 1;
	while (playing) {
		yutani_msg_t * m = yutani_poll(yctx);
		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
							playing = 0;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
					{
						struct yutani_msg_window_focus_change * wf = (void*)m->data;
						yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
						if (win) {
							win->focused = wf->focused;
							decors();
							yutani_flip(yctx, window);
						}
					}
					break;
				case YUTANI_MSG_RESIZE_OFFER:
					{
						struct yutani_msg_window_resize * wr = (void*)m->data;
						resize_finish(wr->width, wr->height);
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						int result = decor_handle_event(yctx, m);
						switch (result) {
							case DECOR_CLOSE:
								playing = 0;
								break;
							default:
								/* Other actions */
								break;
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					playing = 0;
					break;
				default:
					break;
			}
		}
		free(m);
	}

	yutani_close(yctx, window);

	return 0;
}
コード例 #5
0
ファイル: pdfviewer.c プロジェクト: klange/toaru-pdfviewer
int main(int argc, char **argv) {
	fz_document *doc = NULL;
	int c;
	fz_context *ctx;

	fz_var(doc);

	yctx = yutani_init();

	char * _width  = getenv("WIDTH");
	char * _height = getenv("HEIGHT");
	width  = _width  ? atoi(_width)  : 512;
	height = _height ? atoi(_height) : 512;

	init_decorations();

	window = yutani_window_create(yctx, width + decor_width(), height + decor_height());
	yutani_window_move(yctx, window, 50, 50);

	yutani_window_advertise_icon(yctx, window, "PDF Viewer", "pdfviewer");

	gfx_ctx = init_graphics_yutani(window);
	draw_fill(gfx_ctx,rgb(0,0,0));
	render_decorations(window, gfx_ctx, "PDFViewer - Loading...");

	while ((c = fz_getopt(argc, argv, "wf")) != -1) {
		switch (c) {
			case 'f':
				fit = 1;
				break;
		}
	}

	ctx = fz_new_context(NULL, NULL, FZ_STORE_DEFAULT);
	if (!ctx) {
		fprintf(stderr, "Could not initialize fitz context.\n");
		exit(1);
	}

	fz_set_aa_level(ctx, alphabits);
	colorspace = fz_device_rgb;

	fz_try(ctx) {
		while (fz_optind < argc)
		{
			fz_try(ctx)
			{
				filename = argv[fz_optind++];
				files++;

				fz_try(ctx)
				{
					doc = fz_open_document(ctx, filename);
				}
				fz_catch(ctx)
				{
					fz_throw(ctx, "cannot open document: %s", filename);
				}

				if (fz_optind == argc || !isrange(argv[fz_optind]))
					drawrange(ctx, doc, "1-");
				if (fz_optind < argc && isrange(argv[fz_optind]))
					drawrange(ctx, doc, argv[fz_optind++]);

				fz_close_document(doc);
				doc = NULL;
			}
			fz_catch(ctx)
			{
				if (!ignore_errors)
					fz_rethrow(ctx);

				fz_close_document(doc);
				doc = NULL;
				fz_warn(ctx, "ignoring error in '%s'", filename);
			}
		}
	}
	fz_catch(ctx) {
		fz_close_document(doc);
		fprintf(stderr, "error: cannot draw '%s'\n", filename);
		errored = 1;
	}

	fz_free_context(ctx);

	return (errored != 0);
}
コード例 #6
0
ファイル: teapot.c プロジェクト: klange/toaru-opengl
int main(int argc, char** argv) {
	/* default values */
	char * filename = "teapot.obj";
	char * diffuse  = "wood.rgba";
	char * sphere   = "nvidia.rgba";
	int c, index;

	chdir("/opt/examples");

	/* Parse some command-line arguments */
	while ((c = getopt(argc, argv, "d:e:h:s:")) != -1) {
		switch (c) {
			case 'd':
				diffuse = optarg;
				break;
			case 'e':
				sphere = optarg;
				break;
			case 's':
				/* Set scale */
				scale = atof(optarg);
				break;
			case 'h':
				cam_offset = atof(optarg);
				break;
			default:
				/* Uh, that's it for -args */
				printf("Unrecognized argument!\n");
				break;
		}
	}
	/* Get an optional filename from the last non-- parameter */
	for (index = optind; index < argc; ++index) {
		filename = argv[index];
	}

	printf("Press q to exit.\n");

	yctx = yutani_init();
	wina = yutani_window_create(yctx, 500, 500);
	yutani_window_move(yctx, wina, 100, 100);
	ctx = init_graphics_yutani_double_buffer(wina);
	draw_fill(ctx, rgb(0,0,0));
	yutani_window_update_shape(yctx, wina, YUTANI_SHAPE_THRESHOLD_HALF);

	yutani_window_advertise_icon(yctx, wina, "GL Teapot", "teapot");

	OSMesaContext gl_ctx = OSMesaCreateContext(OSMESA_BGRA, NULL);
	if (resize(ctx, gl_ctx)) {
		fprintf(stderr, "%s: Something bad happened.\n", argv[0]);
		goto finish;
	}

	/* Load up the file, set everything else up */
	init (filename, diffuse, sphere);

	/* XXX add a method to query if there are available packets in pex */
	pthread_t thread;
	pthread_create(&thread, NULL, draw_thread, NULL);

	while (!quit) {
		yutani_msg_t * m = yutani_poll(yctx);
		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN) {
							keyboard(ke->event.keycode, 0, 0);
						}
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						struct yutani_msg_window_mouse_event * me = (void*)m->data;
						if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
							yutani_window_drag_start(yctx, wina);
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					quit = 1;
					break;
				default:
					break;
			}
			free(m);
		}
	}

finish:
	OSMesaDestroyContext(gl_ctx);
	yutani_close(yctx, wina);

	return 0;
}
コード例 #7
0
ファイル: gears.c プロジェクト: etel/ponyos
int main (int argc, char ** argv) {
	yutani_t * yctx;
	yutani_window_t * wina;
	gfx_context_t * ctx;
	int should_exit = 0;
	int blur = 0;
	int stopped = 0;

	int left = 30;
	int top  = 30;

	int width  = 500;
	int height = 500;

	yctx = yutani_init();
	wina = yutani_window_create(yctx, width, height);
	yutani_window_move(yctx, wina, left, top);
	ctx = init_graphics_yutani_double_buffer(wina);
	draw_fill(ctx, rgb(0,0,0));
	yutani_window_update_shape(yctx, wina, YUTANI_SHAPE_THRESHOLD_HALF);

	yutani_window_advertise_icon(yctx, wina, "Mesa Gears", "gears");

	OSMesaContext gl_ctx = OSMesaCreateContext(OSMESA_BGRA, NULL);
	if (resize(ctx, gl_ctx)) {
		fprintf(stderr, "%s: Something bad happened.\n", argv[0]);
		goto finish;
	}

	init();

	while (!should_exit) {
		yutani_msg_t * m = yutani_poll_async(yctx);
		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN) {
							switch (ke->event.keycode) {
								case 'q':
									should_exit = 1;
									free(m);
									goto finish;
								case 'b':
									blur = (1-blur);
									break;
								case 's':
									stopped = (1-stopped);
									break;
								case KEY_ARROW_LEFT:
									view_roty += 5.0;
									break;
								case KEY_ARROW_RIGHT:
									view_roty -= 5.0;
									break;
								case KEY_ARROW_UP:
									view_rotx += 5.0;
									break;
								case KEY_ARROW_DOWN:
									view_rotx -= 5.0;
									break;
								default:
									break;
							}
						}
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						struct yutani_msg_window_mouse_event * me = (void*)m->data;
						if (me->command == YUTANI_MOUSE_EVENT_DOWN && me->buttons & YUTANI_MOUSE_BUTTON_LEFT) {
							yutani_window_drag_start(yctx, wina);
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					should_exit = 1;
					break;
				case YUTANI_MSG_RESIZE_OFFER:
					{
						struct yutani_msg_window_resize * wr = (void*)m->data;
						yutani_window_resize_accept(yctx, wina, wr->width, wr->height);
						reinit_graphics_yutani(ctx, wina);
						resize(ctx, gl_ctx);
						draw();
						yutani_window_resize_done(yctx, wina);
						flip(ctx);
						yutani_flip(yctx, wina);
						yutani_window_update_shape(yctx, wina, 1);
						/* Reset statistics */
						frames = 0;
						start_time = 0;
					}
				default:
					break;
			}
			free(m);
		}
		fps();
		if (!stopped) {
			angle += 0.2;
		}
		draw();
		if (blur) {
			blur_context_box(ctx, 20);
		}
		flip(ctx);
		yutani_flip(yctx, wina);
		syscall_yield();
	}

finish:
	OSMesaDestroyContext(gl_ctx);
	yutani_close(yctx, wina);

	return 0;
}
コード例 #8
0
ファイル: panel.c プロジェクト: ETroll/toaruos
/* Callback for mouse events */
static void panel_check_click(struct yutani_msg_window_mouse_event * evt) {
	if (evt->wid == panel->wid) {
		if (evt->command == YUTANI_MOUSE_EVENT_CLICK) {
			/* Up-down click */
			if (evt->new_x >= width - 24 ) {
				yutani_session_end(yctx);
				_continue = 0;
			} else if (evt->new_x < APP_OFFSET) {
				if (!appmenu) {
					appmenu = yutani_window_create(yctx, APPMENU_WIDTH + APPMENU_PAD_RIGHT, APPMENU_ITEM_HEIGHT * appmenu_items_count + APPMENU_PAD_BOTTOM);
					yutani_window_move(yctx, appmenu, 0, PANEL_HEIGHT);
					bctx = init_graphics_yutani_double_buffer(appmenu);
					redraw_appmenu(-1);
					yutani_focus_window(yctx, appmenu->wid);
				} else {
					/* ??? */
				}
			} else if (evt->new_x > WIDGET_POSITION(1) && evt->new_x < WIDGET_POSITION(0)) {
				/* TODO: More generic widget click handling */
				/* TODO: Show the volume manager */
			} else if (evt->new_x >= APP_OFFSET && evt->new_x < LEFT_BOUND) {
				for (int i = 0; i < MAX_WINDOW_COUNT; ++i) {
					if (ads_by_l[i] == NULL) break;
					if (evt->new_x >= ads_by_l[i]->left && evt->new_x < ads_by_l[i]->left + TOTAL_CELL_WIDTH) {
						yutani_focus_window(yctx, ads_by_l[i]->wid);
						break;
					}
				}
			}
		} else if (evt->command == YUTANI_MOUSE_EVENT_MOVE || evt->command == YUTANI_MOUSE_EVENT_ENTER) {
			/* Movement, or mouse entered window */
			if (evt->new_y < PANEL_HEIGHT) {
				for (int i = 0; i < MAX_WINDOW_COUNT; ++i) {
					if (ads_by_l[i] == NULL) {
						set_focused(-1);
						break;
					}
					if (evt->new_x >= ads_by_l[i]->left && evt->new_x < ads_by_l[i]->left + TOTAL_CELL_WIDTH) {
						set_focused(i);
						break;
					}
				}
			} else {
				set_focused(-1);
			}

			int scroll_direction = 0;
			if (evt->buttons & YUTANI_MOUSE_SCROLL_UP) scroll_direction = -1;
			else if (evt->buttons & YUTANI_MOUSE_SCROLL_DOWN) scroll_direction = 1;

			if (scroll_direction) {
				if (evt->new_x > WIDGET_POSITION(1) && evt->new_y < WIDGET_POSITION(0)) {
					if (scroll_direction == 1) {
						volume_lower();
					} else if (scroll_direction == -1) {
						volume_raise();
					}
				} else if (evt->new_x >= APP_OFFSET && evt->new_x < LEFT_BOUND) {
					if (scroll_direction != 0) {
						struct window_ad * last = window_list->tail ? window_list->tail->value : NULL;
						int focus_next = 0;
						foreach(node, window_list) {
							struct window_ad * ad = node->value;
							if (focus_next) {
								yutani_focus_window(yctx, ad->wid);
								return;
							}
							if (ad->flags & 1) {
								if (scroll_direction == -1) {
									yutani_focus_window(yctx, last->wid);
									return;
								}
								if (scroll_direction == 1) {
									focus_next = 1;
								}
							}
							last = ad;
						}
						if (focus_next && window_list->head) {
							struct window_ad * ad = window_list->head->value;
							yutani_focus_window(yctx, ad->wid);
							return;
						}
					}
				}
			}
		} else if (evt->command == YUTANI_MOUSE_EVENT_LEAVE) {
			/* Mouse left panel window */
			set_focused(-1);
		}
	} else {
コード例 #9
0
ファイル: imgviewer.c プロジェクト: ETroll/toaruos
int main(int argc, char * argv[]) {

	if (argc < 2) {
		fprintf(stderr, "Usage: %s image_file\n", argv[0]);
		return 1;
	}

	file_name = argv[1];

	load_sprite_png(&image, argv[1]);

	yctx = yutani_init();

	init_decorations();

	win = yutani_window_create(yctx, image.width + decor_width(), image.height + decor_height());
	yutani_window_move(yctx, win, center_x(image.width + decor_width()), center_y(image.height + decor_height()));
	ctx = init_graphics_yutani_double_buffer(win);

	int stride;

	stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, win->width);
	surface_win = cairo_image_surface_create_for_data(ctx->backbuffer, CAIRO_FORMAT_ARGB32, win->width, win->height, stride);
	cr_win = cairo_create(surface_win);

	yutani_window_advertise_icon(yctx, win, "Image Viewer", "image-viewer");

	redraw();

	yutani_focus_window(yctx, win->wid);

	while (!should_exit) {
		yutani_msg_t * m = yutani_poll(yctx);

		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.key == 'q' && ke->event.action == KEY_ACTION_DOWN) {
							should_exit = 1;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
					{
						struct yutani_msg_window_focus_change * wf = (void*)m->data;
						if (wf->wid == win->wid) {
							win->focused = wf->focused;
							redraw();
						}
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						struct yutani_msg_window_mouse_event * me = (void*)m->data;
						if (me->wid != win->wid) break;
						int result = decor_handle_event(yctx, m);
						switch (result) {
							case DECOR_CLOSE:
								should_exit = 1;
								break;
							default:
								/* Other actions */
								break;
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					should_exit = 1;
					break;
				default:
					break;
			}
			free(m);
		}
	}

	return 0;
}
コード例 #10
0
ファイル: plasma.c プロジェクト: ETroll/toaruos
int main (int argc, char ** argv) {
	yctx = yutani_init();

	win_width  = 100;
	win_height = 100;

	init_decorations();

	off_x = decor_left_width;
	off_y = decor_top_height;

	/* Do something with a window */
	wina = yutani_window_create(yctx, win_width + decor_width(), win_height + decor_height());
	yutani_window_move(yctx, wina, 300, 300);

	ctx = init_graphics_yutani_double_buffer(wina);

	draw_fill(ctx, rgb(0,0,0));
	redraw_borders();
	flip(ctx);
	yutani_flip(yctx, wina);

	yutani_window_advertise(yctx, wina, "Graphics Test");

	pthread_t thread;
	pthread_create(&thread, NULL, draw_thread, NULL);

	while (!should_exit) {
		yutani_msg_t * m = yutani_poll(yctx);
		if (m) {
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
							should_exit = 1;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
					{
						struct yutani_msg_window_focus_change * wf = (void*)m->data;
						yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
						if (win) {
							win->focused = wf->focused;
						}
					}
					break;
				case YUTANI_MSG_SESSION_END:
					should_exit = 1;
					break;
				case YUTANI_MSG_RESIZE_OFFER:
					{
						struct yutani_msg_window_resize * wr = (void*)m->data;
						spin_lock(&draw_lock);
						resize_finish(wr->width, wr->height);
						spin_unlock(&draw_lock);
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					if (decor_handle_event(yctx, m) == DECOR_CLOSE) {
						should_exit = 1;
					}
					break;
				default:
					break;
			}
			free(m);
		}
	}

	yutani_close(yctx, wina);
	return 0;
}
コード例 #11
0
ファイル: imgviewer.c プロジェクト: klange/toaruos
int main(int argc, char * argv[]) {

	static struct option long_opts[] = {
		{"help",   no_argument,       0, '?'},
		{0,0,0,0}
	};

	if (argc > 1) {
		/* Read some arguments */
		int index, c;
		while ((c = getopt_long(argc, argv, "h", long_opts, &index)) != -1) {
			if (!c) {
				if (long_opts[index].flag == 0) {
					c = long_opts[index].val;
				}
			}
			switch (c) {
				case 'h':
					usage(argv);
					exit(0);
					break;
				default:
					break;
			}
		}
	}

	yctx = yutani_init();
	if (!yctx) {
		fprintf(stderr, "%s: failed to connect to compositor\n", argv[0]);
		return 1;
	}
	init_decorations();

	struct decor_bounds bounds;
	decor_get_bounds(NULL, &bounds);

	decor_left_width = bounds.left_width;
	decor_top_height = bounds.top_height;
	decor_right_width = bounds.right_width;
	decor_bottom_height = bounds.bottom_height;
	decor_width = bounds.width;
	decor_height = bounds.height;

	if (strstr(argv[optind],".jpg")) {
		load_sprite_jpg(&img, argv[optind]);
	} else {
		load_sprite(&img, argv[optind]);
	}
	if (!img.width) {
		fprintf(stderr, "%s: failed to open image %s\n", argv[0], argv[optind]);
		return 1;
	}
	img.alpha = ALPHA_EMBEDDED;

	width = img.width;
	height = img.height;

	window = yutani_window_create(yctx, width + decor_width, height + decor_height);
	yutani_window_move(yctx, window, left, top);

	yutani_window_advertise_icon(yctx, window, APPLICATION_TITLE, "imgviewer");

	ctx = init_graphics_yutani_double_buffer(window);

	redraw();
	yutani_flip(yctx, window);

	int playing = 1;
	while (playing) {
		yutani_msg_t * m = yutani_poll(yctx);
		while (m) {
			if (menu_process_event(yctx, m)) {
				/* just decorations should be fine */
				decors();
				flip(ctx);
				yutani_flip(yctx, window);
			}
			switch (m->type) {
				case YUTANI_MSG_KEY_EVENT:
					{
						struct yutani_msg_key_event * ke = (void*)m->data;
						if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
							playing = 0;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_FOCUS_CHANGE:
					{
						struct yutani_msg_window_focus_change * wf = (void*)m->data;
						yutani_window_t * win = hashmap_get(yctx->windows, (void*)wf->wid);
						if (win && win == window) {
							win->focused = wf->focused;
							decors();
							flip(ctx);
							yutani_flip(yctx, window);
						}
					}
					break;
				case YUTANI_MSG_RESIZE_OFFER:
					{
						struct yutani_msg_window_resize * wr = (void*)m->data;
						resize_finish(wr->width, wr->height);
					}
					break;
				case YUTANI_MSG_WINDOW_MOUSE_EVENT:
					{
						struct yutani_msg_window_mouse_event * me = (void*)m->data;
						int result = decor_handle_event(yctx, m);
						switch (result) {
							case DECOR_CLOSE:
								playing = 0;
								break;
							case DECOR_RIGHT:
								/* right click in decoration, show appropriate menu */
								decor_show_default_menu(window, window->x + me->new_x, window->y + me->new_y);
								break;
							default:
								/* Other actions */
								break;
						}
					}
					break;
				case YUTANI_MSG_WINDOW_CLOSE:
				case YUTANI_MSG_SESSION_END:
					playing = 0;
					break;
				default:
					break;
			}
			free(m);
			m = yutani_poll_async(yctx);
		}
	}

	yutani_close(yctx, window);

	return 0;
}