|
@@ -13,7 +13,10 @@ typedef enum {
|
|
WindowState = 6,
|
|
WindowState = 6,
|
|
KeyDown = 7,
|
|
KeyDown = 7,
|
|
KeyUp = 8,
|
|
KeyUp = 8,
|
|
- TextInput = 9
|
|
|
|
|
|
+ TextInput = 9,
|
|
|
|
+ DropStart = 10,
|
|
|
|
+ DropFile = 11,
|
|
|
|
+ DropEnd = 12,
|
|
} EventType;
|
|
} EventType;
|
|
|
|
|
|
typedef enum {
|
|
typedef enum {
|
|
@@ -52,6 +55,7 @@ typedef struct {
|
|
bool keyRepeat;
|
|
bool keyRepeat;
|
|
int controller;
|
|
int controller;
|
|
int value;
|
|
int value;
|
|
|
|
+ vbyte* dropFile;
|
|
} dx_event;
|
|
} dx_event;
|
|
|
|
|
|
typedef struct {
|
|
typedef struct {
|
|
@@ -459,6 +463,47 @@ static LRESULT CALLBACK WndProc( HWND wnd, UINT umsg, WPARAM wparam, LPARAM lpar
|
|
return TRUE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
|
|
+ case WM_DROPFILES:
|
|
|
|
+ {
|
|
|
|
+ HDROP drop = (HDROP)wparam;
|
|
|
|
+ UINT count = DragQueryFileW(drop, 0xFFFFFFFF, NULL, 0);
|
|
|
|
+
|
|
|
|
+ POINT dragPoint;
|
|
|
|
+ if ( !DragQueryPoint(drop, &dragPoint) ) {
|
|
|
|
+ dragPoint.x = 0L;
|
|
|
|
+ dragPoint.y = 0L;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ e = addEvent(wnd, DropStart);
|
|
|
|
+ e->value = count;
|
|
|
|
+ e->mouseX = (int)dragPoint.x;
|
|
|
|
+ e->mouseY = (int)dragPoint.y;
|
|
|
|
+
|
|
|
|
+ for ( UINT i = 0; i < count; i++ ) {
|
|
|
|
+ UINT size = DragQueryFileW(drop, i, NULL, 0) + 1; // + zero terminator
|
|
|
|
+ // We have to make a temporary unmanaged buffer copy due to async nature of event being
|
|
|
|
+ // processed and collected by Haxe event loop, and using GC-allocated buffer risks
|
|
|
|
+ // resulting in garbage data if GC is ran at any point inbetween due to freed buffer.
|
|
|
|
+ // As a consequence, this event requires checks during fetching of the next event
|
|
|
|
+ // (and window destruction) in order to ensure Haxe side gets proper buffer without memory leaks.
|
|
|
|
+ vbyte* buffer = malloc(size * sizeof(WCHAR));
|
|
|
|
+ if ( DragQueryFileW(drop, i, (LPWSTR)buffer, size) ) {
|
|
|
|
+ e = addEvent(wnd, DropFile);
|
|
|
|
+ e->value = size * sizeof(WCHAR);
|
|
|
|
+ e->dropFile = buffer;
|
|
|
|
+ e->mouseX = (int)dragPoint.x;
|
|
|
|
+ e->mouseY = (int)dragPoint.y;
|
|
|
|
+ } else {
|
|
|
|
+ free(buffer);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ e = addEvent(wnd, DropEnd);
|
|
|
|
+ e->value = count;
|
|
|
|
+ e->mouseX = (int)dragPoint.x;
|
|
|
|
+ e->mouseY = (int)dragPoint.y;
|
|
|
|
+ DragFinish(drop);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
case WM_CLOSE:
|
|
case WM_CLOSE:
|
|
addEvent(wnd, Quit);
|
|
addEvent(wnd, Quit);
|
|
return 0;
|
|
return 0;
|
|
@@ -704,6 +749,11 @@ HL_PRIM void HL_NAME(win_destroy)(dx_window *win) {
|
|
ClipCursor(NULL);
|
|
ClipCursor(NULL);
|
|
}
|
|
}
|
|
dx_events *buf = get_events(win);
|
|
dx_events *buf = get_events(win);
|
|
|
|
+ // See WM_DROPFILES comment regarding GC
|
|
|
|
+ for ( int i = buf->next_event; i < buf->event_count; i++ ) {
|
|
|
|
+ if ( buf->events[i].dropFile != NULL )
|
|
|
|
+ free(buf->events[i].dropFile);
|
|
|
|
+ }
|
|
free(buf);
|
|
free(buf);
|
|
SetWindowLongPtr(win,GWLP_USERDATA,0);
|
|
SetWindowLongPtr(win,GWLP_USERDATA,0);
|
|
DestroyWindow(win);
|
|
DestroyWindow(win);
|
|
@@ -722,6 +772,13 @@ HL_PRIM bool HL_NAME(win_get_next_event)( dx_window *win, dx_event *e ) {
|
|
}
|
|
}
|
|
save = e->t;
|
|
save = e->t;
|
|
memcpy(e,&buf->events[buf->next_event++],sizeof(dx_event));
|
|
memcpy(e,&buf->events[buf->next_event++],sizeof(dx_event));
|
|
|
|
+ if ( e->type == DropFile ) {
|
|
|
|
+ // See WM_DROPFILES comment regarding GC
|
|
|
|
+ vbyte* unmanaged = e->dropFile;
|
|
|
|
+ e->dropFile = hl_copy_bytes(unmanaged, e->value);
|
|
|
|
+ free(unmanaged);
|
|
|
|
+ buf->events[buf->next_event - 1].dropFile = NULL;
|
|
|
|
+ }
|
|
e->t = save;
|
|
e->t = save;
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -754,6 +811,10 @@ HL_PRIM bool HL_NAME(win_get_relative_mouse_mode)() {
|
|
return relative_mouse;
|
|
return relative_mouse;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+HL_PRIM void HL_NAME(win_set_drag_accept_files)( dx_window* wnd, bool enabled ) {
|
|
|
|
+ DragAcceptFiles(wnd, enabled);
|
|
|
|
+}
|
|
|
|
+
|
|
HL_PRIM int HL_NAME(get_screen_width)() {
|
|
HL_PRIM int HL_NAME(get_screen_width)() {
|
|
return GetSystemMetrics(SM_CXSCREEN);
|
|
return GetSystemMetrics(SM_CXSCREEN);
|
|
}
|
|
}
|
|
@@ -875,6 +936,7 @@ DEFINE_PRIM(_BOOL, set_cursor_pos, _I32 _I32);
|
|
DEFINE_PRIM(_BOOL, win_set_cursor_pos, TWIN _I32 _I32);
|
|
DEFINE_PRIM(_BOOL, win_set_cursor_pos, TWIN _I32 _I32);
|
|
DEFINE_PRIM(_BOOL, win_set_relative_mouse_mode, TWIN _BOOL);
|
|
DEFINE_PRIM(_BOOL, win_set_relative_mouse_mode, TWIN _BOOL);
|
|
DEFINE_PRIM(_BOOL, win_get_relative_mouse_mode, _NO_ARG);
|
|
DEFINE_PRIM(_BOOL, win_get_relative_mouse_mode, _NO_ARG);
|
|
|
|
+DEFINE_PRIM(_VOID, win_set_drag_accept_files, TWIN _BOOL);
|
|
DEFINE_PRIM(_ARR, win_get_display_settings, _BYTES);
|
|
DEFINE_PRIM(_ARR, win_get_display_settings, _BYTES);
|
|
DEFINE_PRIM(_DYN, win_get_current_display_setting, _BYTES _BOOL);
|
|
DEFINE_PRIM(_DYN, win_get_current_display_setting, _BYTES _BOOL);
|
|
DEFINE_PRIM(_I32, win_change_display_setting, _BYTES _DYN);
|
|
DEFINE_PRIM(_I32, win_change_display_setting, _BYTES _DYN);
|