x11display: fix Xlib thread safety problems

This commit is contained in:
rdb 2018-07-11 13:32:39 +02:00
parent 55146b9f82
commit ff3d005230

View File

@ -136,10 +136,11 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
*/ */
x11GraphicsWindow:: x11GraphicsWindow::
~x11GraphicsWindow() { ~x11GraphicsWindow() {
pmap<Filename, X11_Cursor>::iterator it; if (!_cursor_filenames.empty()) {
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
for (it = _cursor_filenames.begin(); it != _cursor_filenames.end(); it++) { for (auto item : _cursor_filenames) {
XFreeCursor(_display, it->second); XFreeCursor(_display, item.second);
}
} }
} }
@ -157,17 +158,21 @@ get_pointer(int device) const {
result = _input_devices[device].get_pointer(); result = _input_devices[device].get_pointer();
// We recheck this immediately to get the most up-to-date value. // We recheck this immediately to get the most up-to-date value, but we
if (device == 0 && !_dga_mouse_enabled && result._in_window) { // won't bother waiting for the lock if we can't.
if (device == 0 && !_dga_mouse_enabled && result._in_window &&
x11GraphicsPipe::_x_mutex.try_lock()) {
XEvent event; XEvent event;
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
if (XQueryPointer(_display, _xwindow, &event.xbutton.root, if (XQueryPointer(_display, _xwindow, &event.xbutton.root,
&event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root, &event.xbutton.window, &event.xbutton.x_root, &event.xbutton.y_root,
&event.xbutton.x, &event.xbutton.y, &event.xbutton.state)) { &event.xbutton.x, &event.xbutton.y, &event.xbutton.state)) {
double time = ClockObject::get_global_clock()->get_real_time(); double time = ClockObject::get_global_clock()->get_real_time();
result._xpos = event.xbutton.x; result._xpos = event.xbutton.x;
result._ypos = event.xbutton.y; result._ypos = event.xbutton.y;
((GraphicsWindowInputDevice &)_input_devices[0]).set_pointer(result._in_window, result._xpos, result._ypos, time); ((GraphicsWindowInputDevice &)_input_devices[0]).set_pointer_in_window(result._xpos, result._ypos, time);
} }
x11GraphicsPipe::_x_mutex.release();
} }
} }
return result; return result;
@ -197,6 +202,7 @@ move_pointer(int device, int x, int y) {
const MouseData &md = _input_devices[0].get_pointer(); const MouseData &md = _input_devices[0].get_pointer();
if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) { if (!md.get_in_window() || md.get_x() != x || md.get_y() != y) {
if (!_dga_mouse_enabled) { if (!_dga_mouse_enabled) {
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y); XWarpPointer(_display, None, _xwindow, 0, 0, 0, 0, x, y);
} }
_input_devices[0].set_pointer_in_window(x, y); _input_devices[0].set_pointer_in_window(x, y);
@ -532,6 +538,8 @@ set_properties_now(WindowProperties &properties) {
x11GraphicsPipe *x11_pipe; x11GraphicsPipe *x11_pipe;
DCAST_INTO_V(x11_pipe, _pipe); DCAST_INTO_V(x11_pipe, _pipe);
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
// We're either going into or out of fullscreen, or are in fullscreen and // We're either going into or out of fullscreen, or are in fullscreen and
// are changing the resolution. // are changing the resolution.
bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen(); bool is_fullscreen = _properties.has_fullscreen() && _properties.get_fullscreen();
@ -858,6 +866,7 @@ close_window() {
_gsg.clear(); _gsg.clear();
} }
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
if (_ic != (XIC)nullptr) { if (_ic != (XIC)nullptr) {
XDestroyIC(_ic); XDestroyIC(_ic);
_ic = (XIC)nullptr; _ic = (XIC)nullptr;
@ -916,6 +925,9 @@ open_window() {
_properties.set_size(100, 100); _properties.set_size(100, 100);
} }
// Make sure we are not making X11 calls from other threads.
LightReMutexHolder holder(x11GraphicsPipe::_x_mutex);
if (_properties.get_fullscreen() && x11_pipe->_have_xrandr) { if (_properties.get_fullscreen() && x11_pipe->_have_xrandr) {
XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root()); XRRScreenConfiguration* conf = _XRRGetScreenInfo(_display, x11_pipe->get_root());
if (_orig_size_id == (SizeID) -1) { if (_orig_size_id == (SizeID) -1) {
@ -1059,6 +1071,8 @@ open_window() {
* If already_mapped is true, the window has already been mapped (manifested) * If already_mapped is true, the window has already been mapped (manifested)
* on the display. This means we may need to use a different action in some * on the display. This means we may need to use a different action in some
* cases. * cases.
*
* Assumes the X11 lock is held.
*/ */
void x11GraphicsWindow:: void x11GraphicsWindow::
set_wm_properties(const WindowProperties &properties, bool already_mapped) { set_wm_properties(const WindowProperties &properties, bool already_mapped) {