improve wait of x11 event to avoid blocking
This commit is contained in:
parent
02676e9c75
commit
0f66b0cb26
@ -622,6 +622,7 @@ namespace detail
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
|
++(root_runtime->x11msg.config);
|
||||||
if(msgwnd->dimension.width != static_cast<unsigned>(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast<unsigned>(xevent.xconfigure.height))
|
if(msgwnd->dimension.width != static_cast<unsigned>(xevent.xconfigure.width) || msgwnd->dimension.height != static_cast<unsigned>(xevent.xconfigure.height))
|
||||||
{
|
{
|
||||||
auto & cf = xevent.xconfigure;
|
auto & cf = xevent.xconfigure;
|
||||||
@ -890,7 +891,12 @@ namespace detail
|
|||||||
case MapNotify:
|
case MapNotify:
|
||||||
case UnmapNotify:
|
case UnmapNotify:
|
||||||
if(xevent.type == MapNotify)
|
if(xevent.type == MapNotify)
|
||||||
|
{
|
||||||
|
++(root_runtime->x11msg.map);
|
||||||
x11_apply_exposed_position(native_window);
|
x11_apply_exposed_position(native_window);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++(root_runtime->x11msg.unmap);
|
||||||
|
|
||||||
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
brock.event_expose(msgwnd, (xevent.type == MapNotify));
|
||||||
context.platform.motion_window = nullptr;
|
context.platform.motion_window = nullptr;
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#ifdef NANA_X11
|
||||||
|
# include <atomic>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nana{
|
namespace nana{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@ -75,6 +79,15 @@ namespace nana{
|
|||||||
root_misc(root_misc&&);
|
root_misc(root_misc&&);
|
||||||
root_misc(basic_window * wd, unsigned width, unsigned height);
|
root_misc(basic_window * wd, unsigned width, unsigned height);
|
||||||
~root_misc();
|
~root_misc();
|
||||||
|
|
||||||
|
#ifdef NANA_X11
|
||||||
|
struct x11msg_confirm
|
||||||
|
{
|
||||||
|
std::atomic<std::size_t> config{ 0 };
|
||||||
|
std::atomic<std::size_t> map{ 0 };
|
||||||
|
std::atomic<std::size_t> unmap{ 0 };
|
||||||
|
}x11msg;
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
root_misc(const root_misc&) = delete;
|
root_misc(const root_misc&) = delete;
|
||||||
root_misc& operator=(const root_misc&) = delete;
|
root_misc& operator=(const root_misc&) = delete;
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
# include <map>
|
# include <map>
|
||||||
#elif defined(NANA_X11)
|
#elif defined(NANA_X11)
|
||||||
# include <nana/system/platform.hpp>
|
# include <nana/system/platform.hpp>
|
||||||
|
# include "inner_fwd_implement.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "../../paint/image_accessor.hpp"
|
#include "../../paint/image_accessor.hpp"
|
||||||
@ -203,26 +204,87 @@ namespace nana{
|
|||||||
|
|
||||||
namespace x11_wait
|
namespace x11_wait
|
||||||
{
|
{
|
||||||
|
struct param
|
||||||
|
{
|
||||||
|
Window handle;
|
||||||
|
root_misc * misc;
|
||||||
|
std::size_t comp_value;
|
||||||
|
};
|
||||||
|
|
||||||
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
static Bool configure(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == ConfigureNotify) && (evt->xconfigure.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.config != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == ConfigureNotify))
|
||||||
|
{
|
||||||
|
if(evt->xconfigure.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool map(Display *disp, XEvent *evt, char *arg)
|
static Bool map(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xmap.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.map != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == MapNotify))
|
||||||
|
{
|
||||||
|
if(evt->xmap.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool unmap(Display *disp, XEvent *evt, char *arg)
|
static Bool unmap(Display *disp, XEvent *evt, char *arg)
|
||||||
{
|
{
|
||||||
return disp && evt && arg && (evt->type == MapNotify) && (evt->xunmap.window == *reinterpret_cast<Window*>(arg));
|
auto p = reinterpret_cast<param*>(arg);
|
||||||
|
if(p)
|
||||||
|
{
|
||||||
|
if(p->misc->x11msg.unmap != p->comp_value)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if(disp && evt && (evt->type == UnmapNotify))
|
||||||
|
{
|
||||||
|
if(evt->xunmap.window == p->handle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*))
|
static void x11_wait_for(Window wd, Bool(*pred_fn)(Display*, XEvent*, char*), std::size_t comp_value)
|
||||||
{
|
{
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
x11_wait::param p;
|
||||||
|
p.handle = wd;
|
||||||
|
p.misc = misc;
|
||||||
|
|
||||||
|
if(pred_fn == &x11_wait::configure)
|
||||||
|
p.comp_value = misc->x11msg.config;
|
||||||
|
else if(pred_fn == &x11_wait::map)
|
||||||
|
p.comp_value = misc->x11msg.map;
|
||||||
|
else if(pred_fn == &x11_wait::unmap)
|
||||||
|
p.comp_value = misc->x11msg.unmap;
|
||||||
|
|
||||||
|
//Checks whether the msg is received.
|
||||||
|
if(p.comp_value != comp_value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
p.comp_value = comp_value;
|
||||||
|
|
||||||
XEvent dummy;
|
XEvent dummy;
|
||||||
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&wd));
|
::XPeekIfEvent(restrict::spec.open_display(), &dummy, pred_fn, reinterpret_cast<XPointer>(&p));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -762,13 +824,17 @@ namespace nana{
|
|||||||
if(show == is_window_visible(wd))
|
if(show == is_window_visible(wd))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(wd);
|
||||||
|
|
||||||
if(show)
|
if(show)
|
||||||
{
|
{
|
||||||
|
std::size_t cmp_value = misc->x11msg.map;
|
||||||
|
|
||||||
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
::XMapWindow(disp, reinterpret_cast<Window>(wd));
|
||||||
|
|
||||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||||
//the followed window_visible() call can return the updated visibility value.
|
//the followed window_visible() call can return the updated visibility value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::map, cmp_value);
|
||||||
|
|
||||||
Window grab = restrict::spec.grab(0);
|
Window grab = restrict::spec.grab(0);
|
||||||
if(grab == reinterpret_cast<Window>(wd))
|
if(grab == reinterpret_cast<Window>(wd))
|
||||||
@ -776,10 +842,12 @@ namespace nana{
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::size_t cmp_value = misc->x11msg.unmap;
|
||||||
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
::XUnmapWindow(disp, reinterpret_cast<Window>(wd));
|
||||||
|
|
||||||
//Wait for the mapping notify to update the local attribute of visibility so that
|
//Wait for the mapping notify to update the local attribute of visibility so that
|
||||||
//the followed window_visible() call can return the updated visibility value.
|
//the followed window_visible() call can return the updated visibility value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::unmap, cmp_value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static_cast<void>(active); //eliminate unused parameter compiler warning.
|
static_cast<void>(active); //eliminate unused parameter compiler warning.
|
||||||
@ -1023,11 +1091,15 @@ namespace nana{
|
|||||||
y += origin_y;
|
y += origin_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
::XMoveWindow(disp, reinterpret_cast<Window>(wd), x, y);
|
||||||
|
|
||||||
//Wait for the configuration notify to update the local attribute of position so that
|
//Wait for the configuration notify to update the local attribute of position so that
|
||||||
//the followed window_position() call can return the updated position value.
|
//the followed window_position() call can return the updated position value.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
|
||||||
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1113,6 +1185,9 @@ namespace nana{
|
|||||||
y += origin_y;
|
y += origin_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
::XMoveResizeWindow(disp, reinterpret_cast<Window>(wd), x, y, r.width, r.height);
|
||||||
|
|
||||||
//Wait for the configuration notify to update the local attribute of position so that
|
//Wait for the configuration notify to update the local attribute of position so that
|
||||||
@ -1120,7 +1195,7 @@ namespace nana{
|
|||||||
|
|
||||||
//It seems that XMoveResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
//It seems that XMoveResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
||||||
//to make sure the local attribute is updated.
|
//to make sure the local attribute is updated.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
@ -1287,11 +1362,15 @@ namespace nana{
|
|||||||
hints.min_height = hints.max_height = sz.height;
|
hints.min_height = hints.max_height = sz.height;
|
||||||
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
::XSetWMNormalHints(disp, reinterpret_cast<Window>(wd), &hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto misc = bedrock::instance().wd_manager().root_runtime(reinterpret_cast<native_window_type>(wd));
|
||||||
|
std::size_t cmp_value = misc->x11msg.config;
|
||||||
|
|
||||||
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
::XResizeWindow(disp, reinterpret_cast<Window>(wd), sz.width, sz.height);
|
||||||
|
|
||||||
//It seems that XResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
//It seems that XResizeWindow doesn't need x11_wait_for. But x11_wait_for is still called
|
||||||
//to make sure the local attribute is updated.
|
//to make sure the local attribute is updated.
|
||||||
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure);
|
x11_wait_for(reinterpret_cast<Window>(wd), x11_wait::configure, cmp_value);
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user