x11: Create/destroy window code.

This commit is contained in:
Branimir Karadzic 2014-10-02 19:52:43 -07:00
parent 8dab207b36
commit 0aba867510

View file

@ -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)