Commit 287684ab authored by Niklas Haas's avatar Niklas Haas
Browse files

demos: add support for file drag&drop

I've decided this is by far the easiest way to avoid having to implement
a file picker dialog, which would be significantly harder.

Ideally we should support loading new files in plplay itself this way,
but I couldn't be bothered implementing this yet.
parent fcd80494
......@@ -32,3 +32,4 @@ enum button {
void window_get_cursor(const struct window *window, int *x, int *y);
void window_get_scroll(const struct window *window, float *dx, float *dy);
bool window_get_button(const struct window *window, enum button);
char *window_get_file(const struct window *window);
......@@ -4,6 +4,8 @@
#error Specify exactly one of -DUSE_GL or -DUSE_VK when compiling!
#endif
#include <string.h>
#include "common.h"
#include "window.h"
......@@ -39,6 +41,10 @@ struct priv {
#endif
float scroll_dx, scroll_dy;
char **files;
size_t files_num;
size_t files_size;
bool file_seen;
};
static void err_cb(int code, const char *desc)
......@@ -68,6 +74,28 @@ static void scroll_cb(GLFWwindow *win, double dx, double dy)
p->scroll_dy += dy;
}
static void drop_cb(GLFWwindow *win, int num, const char *files[])
{
struct priv *p = glfwGetWindowUserPointer(win);
for (int i = 0; i < num; i++) {
if (p->files_num == p->files_size) {
size_t new_size = p->files_size ? p->files_size * 2 : 16;
char **new_files = reallocarray(p->files, new_size, sizeof(char *));
if (!new_files)
return;
p->files = new_files;
p->files_size = new_size;
}
char *file = strdup(files[i]);
if (!file)
return;
p->files[p->files_num++] = file;
}
}
struct window *window_create(struct pl_context *ctx, const char *title,
int width, int height, enum winflags flags)
{
......@@ -119,6 +147,7 @@ struct window *window_create(struct pl_context *ctx, const char *title,
glfwSetFramebufferSizeCallback(p->win, resize_cb);
glfwSetWindowCloseCallback(p->win, close_cb);
glfwSetScrollCallback(p->win, scroll_cb);
glfwSetDropCallback(p->win, drop_cb);
#ifdef USE_VK
VkResult err;
......@@ -224,6 +253,10 @@ void window_destroy(struct window **window)
pl_opengl_destroy(&p->gl);
#endif
for (int i = 0; i < p->files_num; i++)
free(p->files[i]);
free(p->files);
glfwTerminate();
free(p);
*window = NULL;
......@@ -266,3 +299,20 @@ void window_get_scroll(const struct window *window, float *dx, float *dy)
*dy = p->scroll_dy;
p->scroll_dx = p->scroll_dy = 0.0;
}
char *window_get_file(const struct window *window)
{
struct priv *p = (struct priv *) window;
if (p->file_seen) {
assert(p->files_num);
free(p->files[0]);
memmove(&p->files[0], &p->files[1], --p->files_num * sizeof(char *));
p->file_seen = false;
}
if (!p->files_num)
return NULL;
p->file_seen = true;
return p->files[0];
}
......@@ -42,6 +42,10 @@ struct priv {
#endif
int scroll_dx, scroll_dy;
char **files;
size_t files_num;
size_t files_size;
bool file_seen;
};
struct window *window_create(struct pl_context *ctx, const char *title,
......@@ -178,6 +182,10 @@ void window_destroy(struct window **window)
SDL_GL_DeleteContext(p->gl_ctx);
#endif
for (int i = 0; i < p->files_num; i++)
SDL_free(p->files[i]);
free(p->files);
SDL_DestroyWindow(p->win);
SDL_Quit();
free(p);
......@@ -207,6 +215,20 @@ static inline void handle_event(struct priv *p, SDL_Event *event)
case SDL_MOUSEWHEEL:
p->scroll_dx += event->wheel.x;
p->scroll_dy += event->wheel.y;
return;
case SDL_DROPFILE:
if (p->files_num == p->files_size) {
size_t new_size = p->files_size ? p->files_size * 2 : 16;
char **new_files = reallocarray(p->files, new_size, sizeof(char *));
if (!new_files)
return;
p->files = new_files;
p->files_size = new_size;
}
p->files[p->files_num++] = event->drop.file;
return;
}
}
......@@ -249,3 +271,20 @@ void window_get_scroll(const struct window *window, float *dx, float *dy)
*dy = p->scroll_dy;
p->scroll_dx = p->scroll_dy = 0;
}
char *window_get_file(const struct window *window)
{
struct priv *p = (struct priv *) window;
if (p->file_seen) {
assert(p->files_num);
SDL_free(p->files[0]);
memmove(&p->files[0], &p->files[1], --p->files_num * sizeof(char *));
p->file_seen = false;
}
if (!p->files_num)
return NULL;
p->file_seen = true;
return p->files[0];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment