mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-25 00:58:30 -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
|
||||
#include <bx/thread.h>
|
||||
#include <bx/os.h>
|
||||
#include <bx/handlealloc.h>
|
||||
#include <string.h> // memset
|
||||
#include <string>
|
||||
|
||||
namespace entry
|
||||
{
|
||||
|
@ -42,6 +44,25 @@ namespace entry
|
|||
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
|
||||
{
|
||||
Context()
|
||||
|
@ -131,9 +152,9 @@ namespace entry
|
|||
m_display = XOpenDisplay(0);
|
||||
|
||||
int32_t screen = DefaultScreen(m_display);
|
||||
int32_t depth = DefaultDepth(m_display, screen);
|
||||
Visual* visual = DefaultVisual(m_display, screen);
|
||||
Window root = RootWindow(m_display, screen);
|
||||
m_depth = DefaultDepth(m_display, screen);
|
||||
m_visual = DefaultVisual(m_display, screen);
|
||||
m_root = RootWindow(m_display, screen);
|
||||
|
||||
XSetWindowAttributes windowAttrs;
|
||||
memset(&windowAttrs, 0, sizeof(windowAttrs) );
|
||||
|
@ -150,12 +171,14 @@ namespace entry
|
|||
| StructureNotifyMask
|
||||
;
|
||||
|
||||
m_window = XCreateWindow(m_display
|
||||
, root
|
||||
m_windowAlloc.alloc();
|
||||
m_window[0] = XCreateWindow(m_display
|
||||
, m_root
|
||||
, 0, 0
|
||||
, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, 0, depth
|
||||
, ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, 0
|
||||
, m_depth
|
||||
, InputOutput
|
||||
, visual
|
||||
, m_visual
|
||||
, CWBorderPixel|CWEventMask
|
||||
, &windowAttrs
|
||||
);
|
||||
|
@ -163,18 +186,18 @@ namespace entry
|
|||
// Clear window to black.
|
||||
XSetWindowAttributes 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";
|
||||
Atom 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);
|
||||
XStoreName(m_display, m_window, "BGFX");
|
||||
XMapWindow(m_display, m_window[0]);
|
||||
XStoreName(m_display, m_window[0], "BGFX");
|
||||
|
||||
//
|
||||
bgfx::x11SetDisplayWindow(m_display, m_window);
|
||||
bgfx::x11SetDisplayWindow(m_display, m_window[0]);
|
||||
|
||||
MainThreadEntry mte;
|
||||
mte.m_argc = _argc;
|
||||
|
@ -223,7 +246,8 @@ namespace entry
|
|||
|
||||
if (MouseButton::None != mb)
|
||||
{
|
||||
m_eventQueue.postMouseEvent(defaultWindow
|
||||
WindowHandle handle = findHandle(xbutton.window);
|
||||
m_eventQueue.postMouseEvent(handle
|
||||
, xbutton.x
|
||||
, xbutton.y
|
||||
, 0
|
||||
|
@ -237,7 +261,8 @@ namespace entry
|
|||
case MotionNotify:
|
||||
{
|
||||
const XMotionEvent& xmotion = event.xmotion;
|
||||
m_eventQueue.postMouseEvent(defaultWindow
|
||||
WindowHandle handle = findHandle(xmotion.window);
|
||||
m_eventQueue.postMouseEvent(handle
|
||||
, xmotion.x
|
||||
, xmotion.y
|
||||
, 0
|
||||
|
@ -266,7 +291,8 @@ namespace entry
|
|||
Key::Enum key = fromXk(keysym);
|
||||
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;
|
||||
|
@ -277,8 +303,12 @@ namespace entry
|
|||
case ResizeRequest:
|
||||
{
|
||||
const XResizeRequestEvent& xresize = event.xresizerequest;
|
||||
XResizeWindow(m_display, m_window, xresize.width, xresize.height);
|
||||
m_eventQueue.postSizeEvent(defaultWindow, xresize.width, xresize.height);
|
||||
XResizeWindow(xresize.display, xresize.window, xresize.width, xresize.height);
|
||||
WindowHandle handle = findHandle(xresize.window);
|
||||
if (isValid(handle) )
|
||||
{
|
||||
m_eventQueue.postSizeEvent(handle, xresize.width, xresize.height);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -287,8 +317,8 @@ namespace entry
|
|||
|
||||
thread.shutdown();
|
||||
|
||||
XUnmapWindow(m_display, m_window);
|
||||
XDestroyWindow(m_display, m_window);
|
||||
XUnmapWindow(m_display, m_window[0]);
|
||||
XDestroyWindow(m_display, m_window[0]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -299,12 +329,97 @@ namespace entry
|
|||
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;
|
||||
Display* m_display;
|
||||
Window m_window;
|
||||
bool m_exit;
|
||||
|
||||
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;
|
||||
|
@ -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)
|
||||
{
|
||||
BX_UNUSED(_x, _y, _width, _height, _flags, _title);
|
||||
WindowHandle handle = { UINT16_MAX };
|
||||
bx::LwMutexScope scope(s_ctx.m_lock);
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -357,16 +493,15 @@ namespace entry
|
|||
ev.serial = 0;
|
||||
ev.send_event = true;
|
||||
ev.display = s_ctx.m_display;
|
||||
ev.window = s_ctx.m_window;
|
||||
ev.window = s_ctx.m_window[0];
|
||||
ev.width = (int)_width;
|
||||
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)
|
||||
{
|
||||
BX_UNUSED(_handle);
|
||||
XStoreName(s_ctx.m_display, s_ctx.m_window, _title);
|
||||
XStoreName(s_ctx.m_display, s_ctx.m_window[_handle.idx], _title);
|
||||
}
|
||||
|
||||
void toggleWindowFrame(WindowHandle _handle)
|
||||
|
|
Loading…
Reference in a new issue