port from xcb to x11
This commit is contained in:
parent
2ba1ae480c
commit
a221c1d5ce
@ -1,20 +1,22 @@
|
||||
//#pragma attribute(push, nogc, nothrow)
|
||||
|
||||
#ifdef __linux__
|
||||
# include <xcb/xcb.h>
|
||||
# include <xcb/xfixes.h>
|
||||
# define XLIB_ILLEGAL_ACCESS
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/XKBlib.h>
|
||||
# include <X11/Xlib-xcb.h>
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/keysym.h>
|
||||
# include <X11/extensions/Xfixes.h>
|
||||
# include <X11/Xatom.h>
|
||||
# include <X11/Xutil.h>
|
||||
|
||||
# include <ft2build.h>
|
||||
# include <GL/glx.h>
|
||||
# include <GL/glxext.h>
|
||||
# include FT_FREETYPE_H
|
||||
# include FT_GLYPH_H
|
||||
#endif
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "external/stb/stb_image.h"
|
||||
|
||||
#include "external/stb/stb_image_write.h"
|
||||
|
||||
424
platform.d
424
platform.d
@ -410,8 +410,8 @@ struct Selection
|
||||
{
|
||||
bool owned;
|
||||
u8[] data;
|
||||
xcb_atom_t target;
|
||||
xcb_atom_t xmode;
|
||||
Atom target;
|
||||
Atom xmode;
|
||||
}
|
||||
|
||||
enum Atoms
|
||||
@ -429,15 +429,15 @@ enum Atoms
|
||||
}
|
||||
|
||||
const char[][] ATOM_STRS = [
|
||||
CastStr!(char)("TARGETS"),
|
||||
CastStr!(char)("MULTIPLE"),
|
||||
CastStr!(char)("TIMESTAMP"),
|
||||
CastStr!(char)("INCR"),
|
||||
CastStr!(char)("CLIPBOARD"),
|
||||
CastStr!(char)("UTF8_STRING"),
|
||||
CastStr!(char)("WM_PROTOCOLS"),
|
||||
CastStr!(char)("WM_DELETE_WINDOW"),
|
||||
CastStr!(char)("_NET_WM_STATE_HIDDEN"),
|
||||
Atoms.Targets: CastStr!(char)("TARGETS"),
|
||||
Atoms.Multiple: CastStr!(char)("MULTIPLE"),
|
||||
Atoms.Timestamp: CastStr!(char)("TIMESTAMP"),
|
||||
Atoms.Incr: CastStr!(char)("INCR"),
|
||||
Atoms.Clipboard: CastStr!(char)("CLIPBOARD"),
|
||||
Atoms.Utf8String: CastStr!(char)("UTF8_STRING"),
|
||||
Atoms.WMProtocols: CastStr!(char)("WM_PROTOCOLS"),
|
||||
Atoms.DeleteWindow: CastStr!(char)("WM_DELETE_WINDOW"),
|
||||
Atoms.StateHidden: CastStr!(char)("_NET_WM_STATE_HIDDEN"),
|
||||
];
|
||||
|
||||
alias PThreadProc = extern (C) void* function(void*);
|
||||
@ -579,13 +579,16 @@ PushMotion(Inputs* inputs, i32 rel_x, i32 rel_y, i32 x, i32 y)
|
||||
|
||||
struct PlatformWindow
|
||||
{
|
||||
xcb_atom_t[Atoms.max] atoms;
|
||||
Atom[Atoms.max] atoms;
|
||||
Display* display;
|
||||
xcb_connection_t* conn;
|
||||
xcb_screen_t* screen;
|
||||
xcb_window_t window;
|
||||
u16 w;
|
||||
u16 h;
|
||||
Window window;
|
||||
Window root_window;
|
||||
i32 screen_id;
|
||||
// xcb_connection_t* conn;
|
||||
// xcb_screen_t* screen;
|
||||
// xcb_window_t window;
|
||||
u32 w;
|
||||
u32 h;
|
||||
i32 mouse_prev_x;
|
||||
i32 mouse_prev_y;
|
||||
bool locked_cursor;
|
||||
@ -614,25 +617,18 @@ struct Function
|
||||
void* ptr;
|
||||
};
|
||||
|
||||
pragma(inline) bool
|
||||
NilErr(PlatformWindow* window, xcb_void_cookie_t* cookie, xcb_generic_error_t* err)
|
||||
__gshared string WINDOW_ERR_MSG = null;
|
||||
|
||||
string
|
||||
WindowError()
|
||||
{
|
||||
bool result = err == null;
|
||||
pureFree(err);
|
||||
return result;
|
||||
return WINDOW_ERR_MSG;
|
||||
}
|
||||
|
||||
pragma(inline) void
|
||||
CheckErr(PlatformWindow *window, xcb_void_cookie_t *cookie, xcb_generic_error_t *err, string msg)
|
||||
bool
|
||||
CreateWindow(PlatformWindow* window, string name, u32 width, u32 height, XVisualInfo* visual_info = null)
|
||||
{
|
||||
assert(err == null, msg);
|
||||
pureFree(err);
|
||||
};
|
||||
|
||||
PlatformWindow
|
||||
CreateWindow(string name, u16 width, u16 height)
|
||||
{
|
||||
PlatformWindow window = {
|
||||
PlatformWindow wnd = {
|
||||
w: width,
|
||||
h: height,
|
||||
input_mutex: CreateTicketMut(),
|
||||
@ -645,16 +641,116 @@ CreateWindow(string name, u16 width, u16 height)
|
||||
],
|
||||
};
|
||||
|
||||
version(linux)
|
||||
{
|
||||
window.cb_transfer_size = X11_CB_TRANSFER_SIZE_DEFAULT;
|
||||
}
|
||||
*window = wnd;
|
||||
|
||||
assert(width > 0 && height > 0, "CreateWindow error: width and height must be above 0");
|
||||
window.cb_transfer_size = X11_CB_TRANSFER_SIZE_DEFAULT;
|
||||
|
||||
window.display = XOpenDisplay(null);
|
||||
assert(window.display != null, "XOpenDisplay failure");
|
||||
if(!window.display)
|
||||
{
|
||||
WINDOW_ERR_MSG = "Unable to open X11 display";
|
||||
return false;
|
||||
}
|
||||
|
||||
window.root_window = DefaultRootWindow(window.display);
|
||||
if(window.root_window == None)
|
||||
{
|
||||
WINDOW_ERR_MSG = "Unable to retrieve X11 root window";
|
||||
return false;
|
||||
}
|
||||
|
||||
window.screen_id = XDefaultScreen(window.display);
|
||||
|
||||
XSetWindowAttributes attrs = {
|
||||
background_pixmap: None,
|
||||
background_pixel: XBlackPixel(window.display, window.screen_id),
|
||||
};
|
||||
|
||||
i64 value_mask = CWBackPixmap | CWBackPixel;
|
||||
|
||||
if(visual_info)
|
||||
{
|
||||
attrs.colormap = XCreateColormap(window.display, window.root_window, visual_info.visual, AllocNone);
|
||||
value_mask |= CWColormap;
|
||||
}
|
||||
|
||||
auto copy = CopyFromParent;
|
||||
|
||||
window.window = XCreateWindow(
|
||||
window.display,
|
||||
window.root_window,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
(visual_info ? visual_info.depth : cast(i32)copy),
|
||||
InputOutput,
|
||||
(visual_info ? visual_info.visual : cast(Visual*)©),
|
||||
value_mask,
|
||||
&attrs
|
||||
);
|
||||
|
||||
if(window.window == None)
|
||||
{
|
||||
WINDOW_ERR_MSG = "Failed to create X11 window";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(visual_info)
|
||||
{
|
||||
XFree(visual_info);
|
||||
}
|
||||
|
||||
i64 event_mask = KeyPressMask |
|
||||
KeyReleaseMask |
|
||||
ExposureMask |
|
||||
ButtonPressMask |
|
||||
ButtonReleaseMask |
|
||||
PointerMotionMask |
|
||||
StructureNotifyMask |
|
||||
PropertyChangeMask;
|
||||
|
||||
XSelectInput(window.display, window.window, event_mask);
|
||||
|
||||
foreach(atom; Atoms.min .. Atoms.max)
|
||||
{
|
||||
window.atoms[atom] = XInternAtom(window.display, ATOM_STRS[atom].ptr, false);
|
||||
}
|
||||
|
||||
XSetWMProtocols(window.display, window.window, window.atoms.ptr, window.atoms.length);
|
||||
|
||||
XChangeProperty(
|
||||
window.display,
|
||||
window.window,
|
||||
XA_WM_NAME,
|
||||
XA_STRING,
|
||||
8,
|
||||
PropModeReplace,
|
||||
cast(const(u8)*)name.ptr,
|
||||
cast(u32)name.length
|
||||
);
|
||||
XStoreName(window.display, window.window, name.ptr);
|
||||
|
||||
XChangeProperty(
|
||||
window.display,
|
||||
window.window,
|
||||
window.atoms[Atoms.WMProtocols],
|
||||
XA_ATOM,
|
||||
32,
|
||||
PropModeReplace,
|
||||
cast(const(u8)*)&window.atoms[Atoms.DeleteWindow],
|
||||
1
|
||||
);
|
||||
|
||||
int major, minor;
|
||||
XFixesQueryVersion(window.display, &major, &minor);
|
||||
|
||||
XMapWindow(window.display, window.window);
|
||||
|
||||
XFlush(window.display);
|
||||
|
||||
/*
|
||||
window.conn = XGetXCBConnection(window.display);
|
||||
assert(window.conn != null, "XGetXCBConnection failure");
|
||||
|
||||
@ -753,8 +849,9 @@ CreateWindow(string name, u16 width, u16 height)
|
||||
assert(stream_result > 0, "xcb_flush failure");
|
||||
|
||||
xcb_xfixes_query_version(window.conn, 4, 0);
|
||||
*/
|
||||
|
||||
return window;
|
||||
return true;
|
||||
};
|
||||
|
||||
void
|
||||
@ -773,17 +870,9 @@ LockCursor(PlatformWindow* window)
|
||||
u32 counter = 0;
|
||||
for(;;)
|
||||
{
|
||||
xcb_generic_error_t *error;
|
||||
xcb_grab_pointer_cookie_t grab_cookie = xcb_grab_pointer(window.conn, true, window.window, 0, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, window.window, XCB_NONE, XCB_CURRENT_TIME);
|
||||
xcb_grab_pointer_reply_t* grab_reply = xcb_grab_pointer_reply(window.conn, grab_cookie, &error);
|
||||
i32 grab_res = XGrabPointer(window.display, window.window, true, 0, GrabModeAsync, GrabModeAsync, window.window, None, CurrentTime);
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
pureFree(error);
|
||||
pureFree(grab_reply);
|
||||
}
|
||||
|
||||
if(grab_reply.status == XCB_GRAB_STATUS_SUCCESS)
|
||||
if(grab_res == None)
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
@ -810,7 +899,7 @@ UnlockCursor(PlatformWindow* window)
|
||||
{
|
||||
if(window.locked_cursor)
|
||||
{
|
||||
xcb_ungrab_pointer(window.conn, XCB_CURRENT_TIME);
|
||||
XUngrabPointer(window.display, CurrentTime);
|
||||
ShowCursor(window);
|
||||
window.locked_cursor = false;
|
||||
}
|
||||
@ -819,71 +908,78 @@ UnlockCursor(PlatformWindow* window)
|
||||
bool
|
||||
HideCursor(PlatformWindow* window)
|
||||
{
|
||||
xcb_void_cookie_t hide_cursor_cookie = xcb_xfixes_hide_cursor_checked(window.conn, window.window);
|
||||
xcb_generic_error_t *error = xcb_request_check(window.conn, hide_cursor_cookie);
|
||||
return NilErr(window, &hide_cursor_cookie, error);
|
||||
XFixesHideCursor(window.display, window.window);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ShowCursor(PlatformWindow* window)
|
||||
{
|
||||
xcb_void_cookie_t show_cursor_cookie = xcb_xfixes_show_cursor_checked(window.conn, window.window);
|
||||
xcb_generic_error_t *error = xcb_request_check(window.conn, show_cursor_cookie);
|
||||
return NilErr(window, &show_cursor_cookie, error);
|
||||
XFixesShowCursor(window.display, window.window);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FlushEvents(PlatformWindow* window)
|
||||
ClearEvents(PlatformWindow* window)
|
||||
{
|
||||
xcb_generic_event_t* e;
|
||||
do
|
||||
for(;;)
|
||||
{
|
||||
e = xcb_poll_for_event(window.conn);
|
||||
} while (e);
|
||||
XEvent ev;
|
||||
u32 count = XPending(window.display);
|
||||
for(u32 i = 0; i < count; i += 1)
|
||||
{
|
||||
XNextEvent(window.display, &ev);
|
||||
}
|
||||
|
||||
if(count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TransmitSelection(PlatformWindow* w, xcb_selection_request_event_t* ev)
|
||||
TransmitSelection(PlatformWindow* w, XSelectionRequestEvent* ev)
|
||||
{
|
||||
bool result;
|
||||
if(ev.property == XCB_NONE)
|
||||
if(ev.property == None)
|
||||
{
|
||||
ev.property = ev.target;
|
||||
}
|
||||
|
||||
if(ev.target == w.atoms[Atoms.Targets])
|
||||
{
|
||||
xcb_atom_t[3] targets = [
|
||||
Atom[3] targets = [
|
||||
w.atoms[Atoms.Timestamp],
|
||||
w.atoms[Atoms.Targets],
|
||||
w.atoms[Atoms.Utf8String]
|
||||
];
|
||||
|
||||
xcb_change_property(
|
||||
w.conn,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
XChangeProperty(
|
||||
w.display,
|
||||
ev.requestor,
|
||||
ev.property,
|
||||
XCB_ATOM_ATOM,
|
||||
xcb_atom_t.sizeof * 8,
|
||||
targets.length,
|
||||
targets.ptr
|
||||
XA_ATOM,
|
||||
Atom.sizeof * 8,
|
||||
PropModeReplace,
|
||||
cast(const(u8)*)targets.ptr,
|
||||
targets.length
|
||||
);
|
||||
|
||||
result = true;
|
||||
}
|
||||
else if(ev.target == w.atoms[Atoms.Timestamp])
|
||||
{
|
||||
xcb_timestamp_t cur = XCB_CURRENT_TIME;
|
||||
xcb_change_property(
|
||||
w.conn,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
Time cur = CurrentTime;
|
||||
XChangeProperty(
|
||||
w.display,
|
||||
ev.requestor,
|
||||
ev.property,
|
||||
XCB_ATOM_INTEGER,
|
||||
XA_INTEGER,
|
||||
cur.sizeof * 8,
|
||||
1,
|
||||
&cur
|
||||
PropModeReplace,
|
||||
cast(const(u8)*)&cur,
|
||||
1
|
||||
);
|
||||
|
||||
result = true;
|
||||
@ -904,15 +1000,15 @@ TransmitSelection(PlatformWindow* w, xcb_selection_request_event_t* ev)
|
||||
|
||||
if(sel != null && sel.owned && sel.data.length > 0 && sel.target == ev.target)
|
||||
{
|
||||
xcb_change_property(
|
||||
w.conn,
|
||||
XCB_PROP_MODE_REPLACE,
|
||||
XChangeProperty(
|
||||
w.display,
|
||||
ev.requestor,
|
||||
ev.property,
|
||||
ev.target,
|
||||
8,
|
||||
cast(u32)sel.data.length,
|
||||
sel.data.ptr
|
||||
PropModeReplace,
|
||||
cast(const(u8)*)sel.data.ptr,
|
||||
cast(u32)sel.data.length
|
||||
);
|
||||
|
||||
result = true;
|
||||
@ -952,10 +1048,9 @@ ClipboardText(PlatformWindow* w, ClipboardMode mode)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto owner = xcb_get_selection_owner_reply(w.conn, xcb_get_selection_owner(w.conn, sel.xmode), null);
|
||||
scope(exit) pureFree(owner);
|
||||
Window owner = XGetSelectionOwner(w.display, sel.xmode);
|
||||
|
||||
if(owner != null && owner.owner != 0)
|
||||
if(owner == None)
|
||||
{
|
||||
Free(sel.data);
|
||||
sel.data = [];
|
||||
@ -965,8 +1060,8 @@ ClipboardText(PlatformWindow* w, ClipboardMode mode)
|
||||
u64 ticket = w.cb_mut.next_ticket;
|
||||
|
||||
sel.target = w.atoms[Atoms.Utf8String];
|
||||
xcb_convert_selection(w.conn, w.window, sel.xmode, sel.target, sel.xmode, XCB_CURRENT_TIME);
|
||||
xcb_flush(w.conn);
|
||||
XConvertSelection(w.display, sel.xmode, sel.target, sel.xmode, w.window, CurrentTime);
|
||||
XFlush(w.display);
|
||||
|
||||
while(ticket == w.cb_mut.next_ticket) {}
|
||||
|
||||
@ -1009,8 +1104,8 @@ SetClipboard(PlatformWindow* w, u8[] data, ClipboardMode mode)
|
||||
sel.owned = true;
|
||||
sel.target = w.atoms[Atoms.Utf8String];
|
||||
|
||||
xcb_set_selection_owner(w.conn, w.window, sel.xmode, XCB_CURRENT_TIME);
|
||||
xcb_flush(w.conn);
|
||||
XSetSelectionOwner(w.display, sel.xmode, w.window, CurrentTime);
|
||||
XFlush(w.display);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1041,7 +1136,7 @@ GetClipboardSelection(PlatformWindow* w, Selection* sel)
|
||||
}
|
||||
|
||||
void
|
||||
RetrieveSelection(PlatformWindow* w, xcb_selection_notify_event_t* ev)
|
||||
RetrieveSelection(PlatformWindow* w, XSelectionEvent* ev)
|
||||
{
|
||||
Lock(&w.cb_mut);
|
||||
scope(exit) Unlock(&w.cb_mut);
|
||||
@ -1049,41 +1144,32 @@ RetrieveSelection(PlatformWindow* w, xcb_selection_notify_event_t* ev)
|
||||
u8[] buf;
|
||||
u64 buf_size;
|
||||
u64 bytes_after = 1;
|
||||
xcb_get_property_reply_t* reply;
|
||||
xcb_atom_t actual_type;
|
||||
u8 actual_format;
|
||||
Atom actual_type;
|
||||
i32 actual_format;
|
||||
u64 nitems;
|
||||
u8* prop_data;
|
||||
|
||||
if(ev.property == XCB_ATOM_PRIMARY || ev.property == XCB_ATOM_SECONDARY || ev.property == w.atoms[Atoms.Clipboard])
|
||||
if(ev.property == XA_PRIMARY || ev.property == XA_SECONDARY || ev.property == w.atoms[Atoms.Clipboard])
|
||||
{
|
||||
while(bytes_after > 0)
|
||||
{
|
||||
scope(exit) pureFree(reply);
|
||||
scope(exit) XFree(prop_data);
|
||||
|
||||
xcb_get_property_cookie_t cookie = xcb_get_property(
|
||||
w.conn,
|
||||
true,
|
||||
i32 get_res = XGetWindowProperty(
|
||||
w.display,
|
||||
w.window,
|
||||
ev.property,
|
||||
XCB_ATOM_ANY,
|
||||
cast(u32)(buf_size/4),
|
||||
cast(u32)(w.cb_transfer_size/4)
|
||||
cast(u32)(w.cb_transfer_size/4),
|
||||
true,
|
||||
AnyPropertyType,
|
||||
&actual_type,
|
||||
&actual_format,
|
||||
&nitems,
|
||||
&bytes_after,
|
||||
&prop_data
|
||||
);
|
||||
|
||||
reply = xcb_get_property_reply(w.conn, cookie, null);
|
||||
|
||||
if(reply == null || (buf_size > 0 && (reply.format != actual_format || reply.type != actual_type)) || reply.format%8 != 0)
|
||||
{
|
||||
Errf("RetrieveSelection failure: Invalid return value from xcb_get_property_reply");
|
||||
break;
|
||||
}
|
||||
|
||||
if(buf_size == 0)
|
||||
{
|
||||
actual_type = reply.type;
|
||||
actual_format = reply.format;
|
||||
}
|
||||
|
||||
int nitems = xcb_get_property_value_length(reply);
|
||||
if(nitems > 0)
|
||||
{
|
||||
if(buf_size%4 != 0)
|
||||
@ -1092,14 +1178,13 @@ RetrieveSelection(PlatformWindow* w, xcb_selection_notify_event_t* ev)
|
||||
break;
|
||||
}
|
||||
|
||||
u64 unit_size = reply.format/8;
|
||||
buf = Alloc!(u8)(unit_size * (buf_size + nitems));
|
||||
u64 unit_size = actual_format/8;
|
||||
u64 data_len = unit_size * nitems;
|
||||
buf = Realloc!(u8)(buf, data_len + buf_size);
|
||||
|
||||
MemCpy(buf.ptr + buf_size, xcb_get_property_value(reply), nitems * unit_size);
|
||||
buf_size += nitems * unit_size;
|
||||
MemCpy(buf.ptr + buf_size, prop_data, data_len);
|
||||
buf_size += data_len;
|
||||
}
|
||||
|
||||
bytes_after = reply.bytes_after;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1133,9 +1218,9 @@ RetrieveSelection(PlatformWindow* w, xcb_selection_notify_event_t* ev)
|
||||
}
|
||||
|
||||
void
|
||||
ClearSelection(PlatformWindow* w, xcb_selection_clear_event_t* ev)
|
||||
ClearSelection(PlatformWindow* w, XSelectionClearEvent* ev)
|
||||
{
|
||||
if(ev.owner == w.window)
|
||||
if(ev.window == w.window)
|
||||
{
|
||||
foreach(i; CBM.min .. CBM.max)
|
||||
{
|
||||
@ -1163,7 +1248,7 @@ HandleEvents(void* window_ptr)
|
||||
PlatformWindow* w = cast(PlatformWindow*)window_ptr;
|
||||
|
||||
DNode!(SysMessage)* sys_msg = g_NIL_MSG;
|
||||
xcb_generic_event_t* e;
|
||||
XEvent e;
|
||||
|
||||
bool ignore_mouse_events = false;
|
||||
|
||||
@ -1225,34 +1310,33 @@ HandleEvents(void* window_ptr)
|
||||
}
|
||||
}
|
||||
|
||||
e = xcb_poll_for_event(w.conn);
|
||||
|
||||
if(e)
|
||||
if(XPending(w.display))
|
||||
{
|
||||
XNextEvent(w.display, &e);
|
||||
Inputs* inputs = GetInputs(w);
|
||||
|
||||
switch (e.response_type & ~0x80)
|
||||
switch (e.type)
|
||||
{
|
||||
case XCB_CLIENT_MESSAGE:
|
||||
case ClientMessage:
|
||||
{
|
||||
xcb_client_message_event_t* msg = cast(xcb_client_message_event_t*)e;
|
||||
XClientMessageEvent* msg = &e.xclient;
|
||||
if(msg.window != w.window)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if(msg.data.data32[0] == w.atoms[Atoms.DeleteWindow])
|
||||
if(msg.data.l[0] == w.atoms[Atoms.DeleteWindow])
|
||||
{
|
||||
w.close = true;
|
||||
}
|
||||
} break;
|
||||
case XCB_KEY_RELEASE:
|
||||
case XCB_KEY_PRESS:
|
||||
case KeyRelease:
|
||||
case KeyPress:
|
||||
{
|
||||
xcb_key_press_event_t* keyboard_event = cast(xcb_key_press_event_t*)e;
|
||||
XKeyEvent* kb_ev = &e.xkey;
|
||||
|
||||
bool pressed = e.response_type == XCB_KEY_PRESS;
|
||||
xcb_keycode_t code = keyboard_event.detail;
|
||||
bool pressed = e.type == KeyPress;
|
||||
u32 code = kb_ev.keycode;
|
||||
KeySym key_sym = XkbKeycodeToKeysym(w.display, cast(KeyCode)code, 0, 0);
|
||||
Input input = ConvertInput(key_sym);
|
||||
|
||||
@ -1269,37 +1353,38 @@ HandleEvents(void* window_ptr)
|
||||
|
||||
if(input != Input.None)
|
||||
{
|
||||
Push(inputs, input, keyboard_event.event_x, keyboard_event.event_y, pressed, w.modifier);
|
||||
Push(inputs, input, kb_ev.x, kb_ev.y, pressed, w.modifier);
|
||||
}
|
||||
} break;
|
||||
case XCB_BUTTON_PRESS:
|
||||
case XCB_BUTTON_RELEASE:
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
{
|
||||
xcb_button_press_event_t* mouse_event = cast(xcb_button_press_event_t*)e;
|
||||
bool pressed = e.response_type == XCB_BUTTON_PRESS;
|
||||
XButtonEvent* mouse_event = &e.xbutton;
|
||||
|
||||
bool pressed = e.type == ButtonPress;
|
||||
Input input = Input.None;
|
||||
|
||||
switch (mouse_event.detail)
|
||||
switch (mouse_event.button)
|
||||
{
|
||||
case XCB_BUTTON_INDEX_1: input = Input.LeftClick; break;
|
||||
case XCB_BUTTON_INDEX_2: input = Input.MiddleClick; break;
|
||||
case XCB_BUTTON_INDEX_3: input = Input.RightClick; break;
|
||||
case Button1: input = Input.LeftClick; break;
|
||||
case Button2: input = Input.MiddleClick; break;
|
||||
case Button3: input = Input.RightClick; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(input != Input.None)
|
||||
{
|
||||
Push(inputs, input, mouse_event.event_x, mouse_event.event_y, pressed, w.modifier);
|
||||
Push(inputs, input, mouse_event.x, mouse_event.y, pressed, w.modifier);
|
||||
}
|
||||
} break;
|
||||
case XCB_MOTION_NOTIFY:
|
||||
case MotionNotify:
|
||||
{
|
||||
if(ignore_mouse_events) continue;
|
||||
|
||||
xcb_motion_notify_event_t* move_event = cast(xcb_motion_notify_event_t*)e;
|
||||
XMotionEvent* move_event = &e.xmotion;
|
||||
|
||||
i16 x = move_event.event_x;
|
||||
i16 y = move_event.event_y;
|
||||
i32 x = move_event.x;
|
||||
i32 y = move_event.y;
|
||||
|
||||
static bool first = true;
|
||||
if(first)
|
||||
@ -1320,45 +1405,48 @@ HandleEvents(void* window_ptr)
|
||||
if(w.locked_cursor &&
|
||||
(x < WINDOW_EDGE_BUFFER || y < WINDOW_EDGE_BUFFER || x > w.w - WINDOW_EDGE_BUFFER || y > w.h - WINDOW_EDGE_BUFFER))
|
||||
{
|
||||
i16 new_x = cast(i16)(w.w / 2);
|
||||
i16 new_y = cast(i16)(w.h / 2);
|
||||
xcb_warp_pointer(w.conn, w.window, w.window, 0, 0, cast(i16)w.w, cast(i16)w.h, new_x, new_y);
|
||||
i32 new_x = cast(i32)(w.w / 2);
|
||||
i32 new_y = cast(i32)(w.h / 2);
|
||||
XWarpPointer(w.display, w.window, w.window, 0, 0, cast(i16)w.w, cast(i16)w.h, new_x, new_y);
|
||||
w.mouse_prev_x = new_x;
|
||||
w.mouse_prev_y = new_y;
|
||||
ignore_mouse_events = true;
|
||||
}
|
||||
} break;
|
||||
case XCB_CONFIGURE_NOTIFY:
|
||||
case ConfigureNotify:
|
||||
{
|
||||
xcb_configure_notify_event_t* config_event = cast(xcb_configure_notify_event_t*)e;
|
||||
XConfigureEvent* config_event = &e.xconfigure;
|
||||
if(w.w != config_event.width || w.h != config_event.height)
|
||||
{
|
||||
w.w = config_event.width;
|
||||
w.h = config_event.height;
|
||||
}
|
||||
} break;
|
||||
case XCB_SELECTION_CLEAR:
|
||||
case SelectionClear:
|
||||
{
|
||||
ClearSelection(w, cast(xcb_selection_clear_event_t*)e);
|
||||
ClearSelection(w, &e.xselectionclear);
|
||||
} break;
|
||||
case XCB_SELECTION_NOTIFY:
|
||||
case SelectionNotify:
|
||||
{
|
||||
RetrieveSelection(w, cast(xcb_selection_notify_event_t*)e);
|
||||
RetrieveSelection(w, &e.xselection);
|
||||
} break;
|
||||
case XCB_SELECTION_REQUEST:
|
||||
case SelectionRequest:
|
||||
{
|
||||
auto req = cast(xcb_selection_request_event_t*)e;
|
||||
xcb_selection_notify_event_t notify = {
|
||||
response_type: XCB_SELECTION_NOTIFY,
|
||||
time: XCB_CURRENT_TIME,
|
||||
auto req = &e.xselectionrequest;
|
||||
XEvent notify = {
|
||||
xselection: {
|
||||
type: SelectionNotify,
|
||||
time: CurrentTime,
|
||||
display: w.display,
|
||||
requestor: req.requestor,
|
||||
selection: req.selection,
|
||||
target: req.target,
|
||||
property: TransmitSelection(w, req) ? req.property : XCB_NONE,
|
||||
property: TransmitSelection(w, req) ? req.property : None,
|
||||
},
|
||||
};
|
||||
|
||||
xcb_send_event(w.conn, false, req.requestor, XCB_EVENT_MASK_PROPERTY_CHANGE, cast(char*)¬ify);
|
||||
xcb_flush(w.conn);
|
||||
XSendEvent(w.display, req.requestor, false, PropertyChangeMask, ¬ify);
|
||||
XFlush(w.display);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user