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