mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 18:45:54 -05:00
x11: Create/destroy window code.
This commit is contained in:
parent
8dab207b36
commit
0aba867510
1 changed files with 163 additions and 28 deletions
|
@ -15,7 +15,9 @@
|
||||||
#undef None
|
#undef None
|
||||||
#include <bx/thread.h>
|
#include <bx/thread.h>
|
||||||
#include <bx/os.h>
|
#include <bx/os.h>
|
||||||
|
#include <bx/handlealloc.h>
|
||||||
#include <string.h> // memset
|
#include <string.h> // memset
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace entry
|
namespace entry
|
||||||
{
|
{
|
||||||
|
@ -42,6 +44,25 @@ namespace entry
|
||||||
static int32_t threadFunc(void* _userData);
|
static int32_t threadFunc(void* _userData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Msg
|
||||||
|
{
|
||||||
|
Msg()
|
||||||
|
: m_x(0)
|
||||||
|
, m_y(0)
|
||||||
|
, m_width(0)
|
||||||
|
, m_height(0)
|
||||||
|
, m_flags(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t m_x;
|
||||||
|
int32_t m_y;
|
||||||
|
uint32_t m_width;
|
||||||
|
uint32_t m_height;
|
||||||
|
uint32_t m_flags;
|
||||||
|
std::string m_title;
|
||||||
|
};
|
||||||
|
|
||||||
struct Context
|
struct Context
|
||||||
{
|
{
|
||||||
Context()
|
Context()
|
||||||
|
@ -131,9 +152,9 @@ namespace entry
|
||||||
m_display = XOpenDisplay(0);
|
m_display = XOpenDisplay(0);
|
||||||
|
|
||||||
int32_t screen = DefaultScreen(m_display);
|
int32_t screen = DefaultScreen(m_display);
|
||||||
int32_t depth = DefaultDepth(m_display, screen);
|
m_depth = DefaultDepth(m_display, screen);
|
||||||
Visual* visual = DefaultVisual(m_display, screen);
|
m_visual = DefaultVisual(m_display, screen);
|
||||||
Window root = RootWindow(m_display, screen);
|
m_root = RootWindow(m_display, screen);
|
||||||
|
|
||||||
XSetWindowAttributes windowAttrs;
|
XSetWindowAttributes windowAttrs;
|
||||||
memset(&windowAttrs, 0, sizeof(windowAttrs) );
|
memset(&windowAttrs, 0, sizeof(windowAttrs) );
|
||||||
|
@ -150,12 +171,14 @@ namespace entry
|
||||||
| StructureNotifyMask
|
| StructureNotifyMask
|
||||||
;
|
;
|
||||||
|
|
||||||
m_window = XCreateWindow(m_display
|
m_windowAlloc.alloc();
|
||||||
, root
|
m_window[0] = XCreateWindow(m_display
|
||||||
|
, m_root
|
||||||
, 0, 0
|
, 0, 0
|
||||||
, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, 0, depth
|
, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, 0
|
||||||
|
, m_depth
|
||||||
, InputOutput
|
, InputOutput
|
||||||
, visual
|
, m_visual
|
||||||
, CWBorderPixel|CWEventMask
|
, CWBorderPixel|CWEventMask
|
||||||
, &windowAttrs
|
, &windowAttrs
|
||||||
);
|
);
|
||||||
|
@ -163,18 +186,18 @@ namespace entry
|
||||||
// Clear window to black.
|
// Clear window to black.
|
||||||
XSetWindowAttributes attr;
|
XSetWindowAttributes attr;
|
||||||
memset(&attr, 0, sizeof(attr) );
|
memset(&attr, 0, sizeof(attr) );
|
||||||
XChangeWindowAttributes(m_display, m_window, CWBackPixel, &attr);
|
XChangeWindowAttributes(m_display, m_window[0], CWBackPixel, &attr);
|
||||||
|
|
||||||
const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
|
const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
|
||||||
Atom wmDeleteWindow;
|
Atom wmDeleteWindow;
|
||||||
XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow);
|
XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow);
|
||||||
XSetWMProtocols(m_display, m_window, &wmDeleteWindow, 1);
|
XSetWMProtocols(m_display, m_window[0], &wmDeleteWindow, 1);
|
||||||
|
|
||||||
XMapWindow(m_display, m_window);
|
XMapWindow(m_display, m_window[0]);
|
||||||
XStoreName(m_display, m_window, "BGFX");
|
XStoreName(m_display, m_window[0], "BGFX");
|
||||||
|
|
||||||
//
|
//
|
||||||
bgfx::x11SetDisplayWindow(m_display, m_window);
|
bgfx::x11SetDisplayWindow(m_display, m_window[0]);
|
||||||
|
|
||||||
MainThreadEntry mte;
|
MainThreadEntry mte;
|
||||||
mte.m_argc = _argc;
|
mte.m_argc = _argc;
|
||||||
|
@ -223,7 +246,8 @@ namespace entry
|
||||||
|
|
||||||
if (MouseButton::None != mb)
|
if (MouseButton::None != mb)
|
||||||
{
|
{
|
||||||
m_eventQueue.postMouseEvent(defaultWindow
|
WindowHandle handle = findHandle(xbutton.window);
|
||||||
|
m_eventQueue.postMouseEvent(handle
|
||||||
, xbutton.x
|
, xbutton.x
|
||||||
, xbutton.y
|
, xbutton.y
|
||||||
, 0
|
, 0
|
||||||
|
@ -237,7 +261,8 @@ namespace entry
|
||||||
case MotionNotify:
|
case MotionNotify:
|
||||||
{
|
{
|
||||||
const XMotionEvent& xmotion = event.xmotion;
|
const XMotionEvent& xmotion = event.xmotion;
|
||||||
m_eventQueue.postMouseEvent(defaultWindow
|
WindowHandle handle = findHandle(xmotion.window);
|
||||||
|
m_eventQueue.postMouseEvent(handle
|
||||||
, xmotion.x
|
, xmotion.x
|
||||||
, xmotion.y
|
, xmotion.y
|
||||||
, 0
|
, 0
|
||||||
|
@ -266,7 +291,8 @@ namespace entry
|
||||||
Key::Enum key = fromXk(keysym);
|
Key::Enum key = fromXk(keysym);
|
||||||
if (Key::None != key)
|
if (Key::None != key)
|
||||||
{
|
{
|
||||||
m_eventQueue.postKeyEvent(defaultWindow, key, m_modifiers, KeyPress == event.type);
|
WindowHandle handle = findHandle(xkey.window);
|
||||||
|
m_eventQueue.postKeyEvent(handle, key, m_modifiers, KeyPress == event.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -277,8 +303,12 @@ namespace entry
|
||||||
case ResizeRequest:
|
case ResizeRequest:
|
||||||
{
|
{
|
||||||
const XResizeRequestEvent& xresize = event.xresizerequest;
|
const XResizeRequestEvent& xresize = event.xresizerequest;
|
||||||
XResizeWindow(m_display, m_window, xresize.width, xresize.height);
|
XResizeWindow(xresize.display, xresize.window, xresize.width, xresize.height);
|
||||||
m_eventQueue.postSizeEvent(defaultWindow, xresize.width, xresize.height);
|
WindowHandle handle = findHandle(xresize.window);
|
||||||
|
if (isValid(handle) )
|
||||||
|
{
|
||||||
|
m_eventQueue.postSizeEvent(handle, xresize.width, xresize.height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -287,8 +317,8 @@ namespace entry
|
||||||
|
|
||||||
thread.shutdown();
|
thread.shutdown();
|
||||||
|
|
||||||
XUnmapWindow(m_display, m_window);
|
XUnmapWindow(m_display, m_window[0]);
|
||||||
XDestroyWindow(m_display, m_window);
|
XDestroyWindow(m_display, m_window[0]);
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -299,12 +329,97 @@ namespace entry
|
||||||
m_modifiers |= _set ? _modifier : 0;
|
m_modifiers |= _set ? _modifier : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void createWindow(WindowHandle _handle, Msg* msg)
|
||||||
|
{
|
||||||
|
XSetWindowAttributes windowAttrs;
|
||||||
|
memset(&windowAttrs, 0, sizeof(windowAttrs) );
|
||||||
|
windowAttrs.background_pixmap = 0;
|
||||||
|
windowAttrs.border_pixel = 0;
|
||||||
|
windowAttrs.event_mask = 0
|
||||||
|
| ButtonPressMask
|
||||||
|
| ButtonReleaseMask
|
||||||
|
| ExposureMask
|
||||||
|
| KeyPressMask
|
||||||
|
| KeyReleaseMask
|
||||||
|
| PointerMotionMask
|
||||||
|
| ResizeRedirectMask
|
||||||
|
| StructureNotifyMask
|
||||||
|
;
|
||||||
|
|
||||||
|
Window window = XCreateWindow(m_display
|
||||||
|
, m_root
|
||||||
|
, msg->m_x
|
||||||
|
, msg->m_y
|
||||||
|
, msg->m_width
|
||||||
|
, msg->m_height
|
||||||
|
, 0
|
||||||
|
, m_depth
|
||||||
|
, InputOutput
|
||||||
|
, m_visual
|
||||||
|
, CWBorderPixel|CWEventMask
|
||||||
|
, &windowAttrs
|
||||||
|
);
|
||||||
|
m_window[_handle.idx] = window;
|
||||||
|
|
||||||
|
// Clear window to black.
|
||||||
|
XSetWindowAttributes attr;
|
||||||
|
memset(&attr, 0, sizeof(attr) );
|
||||||
|
XChangeWindowAttributes(m_display, window, CWBackPixel, &attr);
|
||||||
|
|
||||||
|
const char* wmDeleteWindowName = "WM_DELETE_WINDOW";
|
||||||
|
Atom wmDeleteWindow;
|
||||||
|
XInternAtoms(m_display, (char **)&wmDeleteWindowName, 1, False, &wmDeleteWindow);
|
||||||
|
XSetWMProtocols(m_display, window, &wmDeleteWindow, 1);
|
||||||
|
|
||||||
|
XMapWindow(m_display, window);
|
||||||
|
XStoreName(m_display, window, msg->m_title.c_str() );
|
||||||
|
|
||||||
|
m_eventQueue.postSizeEvent(_handle, msg->m_width, msg->m_height);
|
||||||
|
|
||||||
|
union cast
|
||||||
|
{
|
||||||
|
void* p;
|
||||||
|
::Window w;
|
||||||
|
};
|
||||||
|
|
||||||
|
cast c;
|
||||||
|
c.w = window;
|
||||||
|
m_eventQueue.postWindowEvent(_handle, c.p);
|
||||||
|
|
||||||
|
delete msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowHandle findHandle(Window _window)
|
||||||
|
{
|
||||||
|
bx::LwMutexScope scope(m_lock);
|
||||||
|
for (uint32_t ii = 0, num = m_windowAlloc.getNumHandles(); ii < num; ++ii)
|
||||||
|
{
|
||||||
|
uint16_t idx = m_windowAlloc.getHandleAt(ii);
|
||||||
|
if (_window == m_window[idx])
|
||||||
|
{
|
||||||
|
WindowHandle handle = { idx };
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowHandle invalid = { UINT16_MAX };
|
||||||
|
return invalid;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t m_modifiers;
|
uint8_t m_modifiers;
|
||||||
Display* m_display;
|
|
||||||
Window m_window;
|
|
||||||
bool m_exit;
|
bool m_exit;
|
||||||
|
|
||||||
EventQueue m_eventQueue;
|
EventQueue m_eventQueue;
|
||||||
|
bx::LwMutex m_lock;
|
||||||
|
bx::HandleAllocT<ENTRY_CONFIG_MAX_WINDOWS> m_windowAlloc;
|
||||||
|
|
||||||
|
int32_t m_depth;
|
||||||
|
Visual* m_visual;
|
||||||
|
Window m_root;
|
||||||
|
|
||||||
|
Display* m_display;
|
||||||
|
Window m_window[ENTRY_CONFIG_MAX_WINDOWS];
|
||||||
|
uint32_t m_flags[ENTRY_CONFIG_MAX_WINDOWS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static Context s_ctx;
|
static Context s_ctx;
|
||||||
|
@ -334,14 +449,35 @@ namespace entry
|
||||||
|
|
||||||
WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
|
WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title)
|
||||||
{
|
{
|
||||||
BX_UNUSED(_x, _y, _width, _height, _flags, _title);
|
bx::LwMutexScope scope(s_ctx.m_lock);
|
||||||
WindowHandle handle = { UINT16_MAX };
|
WindowHandle handle = { s_ctx.m_windowAlloc.alloc() };
|
||||||
|
|
||||||
|
if (isValid(handle) )
|
||||||
|
{
|
||||||
|
Msg* msg = new Msg;
|
||||||
|
msg->m_x = _x;
|
||||||
|
msg->m_y = _y;
|
||||||
|
msg->m_width = _width;
|
||||||
|
msg->m_height = _height;
|
||||||
|
msg->m_title = _title;
|
||||||
|
msg->m_flags = _flags;
|
||||||
|
s_ctx.createWindow(handle, msg);
|
||||||
|
}
|
||||||
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroyWindow(WindowHandle _handle)
|
void destroyWindow(WindowHandle _handle)
|
||||||
{
|
{
|
||||||
BX_UNUSED(_handle);
|
if (isValid(handle) )
|
||||||
|
{
|
||||||
|
s_ctx.m_eventQueue.postWindowEvent(_handle, NULL);
|
||||||
|
XUnmapWindow(s_ctx.m_display, s_ctx.m_window[_handle.idx]);
|
||||||
|
XDestroyWindow(s_ctx.m_display, s_ctx.m_window[_handle.idx]);
|
||||||
|
|
||||||
|
bx::LwMutexScope scope(s_ctx.m_lock);
|
||||||
|
s_ctx.m_windowAlloc.free(_handle.idx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
|
void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y)
|
||||||
|
@ -357,16 +493,15 @@ namespace entry
|
||||||
ev.serial = 0;
|
ev.serial = 0;
|
||||||
ev.send_event = true;
|
ev.send_event = true;
|
||||||
ev.display = s_ctx.m_display;
|
ev.display = s_ctx.m_display;
|
||||||
ev.window = s_ctx.m_window;
|
ev.window = s_ctx.m_window[0];
|
||||||
ev.width = (int)_width;
|
ev.width = (int)_width;
|
||||||
ev.height = (int)_height;
|
ev.height = (int)_height;
|
||||||
XSendEvent(s_ctx.m_display, s_ctx.m_window, false, ResizeRedirectMask, (XEvent*)&ev);
|
XSendEvent(s_ctx.m_display, s_ctx.m_window[0], false, ResizeRedirectMask, (XEvent*)&ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setWindowTitle(WindowHandle _handle, const char* _title)
|
void setWindowTitle(WindowHandle _handle, const char* _title)
|
||||||
{
|
{
|
||||||
BX_UNUSED(_handle);
|
XStoreName(s_ctx.m_display, s_ctx.m_window[_handle.idx], _title);
|
||||||
XStoreName(s_ctx.m_display, s_ctx.m_window, _title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggleWindowFrame(WindowHandle _handle)
|
void toggleWindowFrame(WindowHandle _handle)
|
||||||
|
|
Loading…
Reference in a new issue