summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/x11/platform.cpp180
-rw-r--r--client/x11/red_drawable.cpp7
-rw-r--r--client/x11/red_window.cpp158
-rw-r--r--client/x11/x_icon.cpp13
4 files changed, 314 insertions, 44 deletions
diff --git a/client/x11/platform.cpp b/client/x11/platform.cpp
index ccae8777..9751a308 100644
--- a/client/x11/platform.cpp
+++ b/client/x11/platform.cpp
@@ -65,7 +65,7 @@
#define BOOL bool
#include "named_pipe.h"
-//#define X_DEBUG_SYNC(display) XSync(display, False)
+//#define X_DEBUG_SYNC(display) do { XLockDisplay(display); XSync(display, False); XUnlockDisplay(display); } while(0)
#define X_DEBUG_SYNC(display)
#ifdef HAVE_XRANDR12
#define USE_XRANDR_1_2
@@ -175,10 +175,16 @@ static Platform::ClipboardListener* clipboard_listener = &default_clipboard_list
static const char *atom_name(Atom atom)
{
+ const char *name;
+
if (atom == None)
return "None";
- return XGetAtomName(x_display, atom);
+ XLockDisplay(x_display);
+ name = XGetAtomName(x_display, atom);
+ XUnlockDisplay(x_display);
+
+ return name;
}
static uint32_t get_clipboard_type(Atom target) {
@@ -265,6 +271,7 @@ XEventHandler::XEventHandler(Display& x_display, XContext& win_proc_context)
void XEventHandler::on_event()
{
+ XLockDisplay(x_display);
while (XPending(&_x_display)) {
XPointer proc_pointer;
XEvent event;
@@ -281,8 +288,11 @@ void XEventHandler::on_event()
if (XFindContext(&_x_display, event.xany.window, _win_proc_context, &proc_pointer)) {
THROW("no window proc");
}
+ XUnlockDisplay(x_display);
((XPlatform::win_proc_t)proc_pointer)(event);
+ XLockDisplay(x_display);
}
+ XUnlockDisplay(x_display);
}
Display* XPlatform::get_display()
@@ -315,6 +325,12 @@ XImage *XPlatform::create_x_shm_image(RedDrawable::Format format,
XImage *image;
XShmSegmentInfo *shminfo;
+ /* We need to lock the display early, and force any pending requests to
+ be processed, to make sure that any errors reported by
+ handle_x_errors_stop() are actually ours */
+ XLockDisplay(XPlatform::get_display());
+ XSync(XPlatform::get_display(), False);
+
shminfo = new XShmSegmentInfo;
shminfo->shmid = -1;
shminfo->shmaddr = NULL;
@@ -375,6 +391,8 @@ XImage *XPlatform::create_x_shm_image(RedDrawable::Format format,
the segment if the client crashes. */
shmctl(shminfo->shmid, IPC_RMID, 0);
+ XUnlockDisplay(XPlatform::get_display());
+
image->data = (char *)shminfo->shmaddr;
*shminfo_out = shminfo;
@@ -390,6 +408,7 @@ err2:
}
err1:
+ XUnlockDisplay(XPlatform::get_display());
delete shminfo;
return NULL;
}
@@ -422,6 +441,7 @@ XImage *XPlatform::create_x_image(RedDrawable::Format format,
THROW("Out of memory");
}
+ XLockDisplay(XPlatform::get_display());
if (format == RedDrawable::A1) {
image = XCreateImage(XPlatform::get_display(),
NULL, 1, XYBitmap,
@@ -431,6 +451,7 @@ XImage *XPlatform::create_x_image(RedDrawable::Format format,
visual, depth, ZPixmap,
0, (char *)data, width, height, 32, stride);
}
+ XUnlockDisplay(XPlatform::get_display());
return image;
}
@@ -440,6 +461,7 @@ void XPlatform::free_x_image(XImage *image,
XShmSegmentInfo *shminfo)
{
if (shminfo) {
+ XLockDisplay(XPlatform::get_display());
XShmDetach(XPlatform::get_display(), shminfo);
}
if (image) {
@@ -448,6 +470,7 @@ void XPlatform::free_x_image(XImage *image,
if (shminfo) {
XSync(XPlatform::get_display(), False);
shmdt(shminfo->shmaddr);
+ XUnlockDisplay(XPlatform::get_display());
delete shminfo;
}
}
@@ -477,14 +500,21 @@ XIC XPlatform::get_input_context()
void XPlatform::set_win_proc(Window win, win_proc_t proc)
{
- if (XSaveContext(x_display, win, win_proc_context, (XPointer)proc)) {
+ int res;
+
+ XLockDisplay(x_display);
+ res = XSaveContext(x_display, win, win_proc_context, (XPointer)proc);
+ XUnlockDisplay(x_display);
+ if (res) {
THROW("set win proc failed");
}
}
void XPlatform::cleare_win_proc(Window win)
{
+ XLockDisplay(x_display);
XDeleteContext(x_display, win, win_proc_context);
+ XUnlockDisplay(x_display);
}
void Platform::send_quit_request()
@@ -651,12 +681,15 @@ static void show_scren_info()
int maxWidth;
int maxHeight;
+ XLockDisplay(x_display);
AutoScreenRes res(XRRGetScreenResources(x_display, root_window));
+ XUnlockDisplay(x_display);
if (!res.valid()) {
throw Exception(fmt("%s: get screen resources failed") % __FUNCTION__);
}
+ XLockDisplay(x_display);
XRRGetScreenSizeRange(x_display, root_window, &minWidth, &minHeight,
&maxWidth, &maxHeight);
printf("screen: min %dx%d max %dx%d\n", minWidth, minHeight,
@@ -706,6 +739,7 @@ static void show_scren_info()
crtc_info->x, crtc_info->y,
crtc_info->width, crtc_info->height, crtc_info->mode);
}
+ XUnlockDisplay(x_display);
}
#endif
@@ -767,7 +801,10 @@ XScreen::XScreen(Display* display, int screen)
int root = RootWindow(display, screen);
XWindowAttributes attrib;
+
+ XLockDisplay(display);
XGetWindowAttributes(display, root, &attrib);
+ XUnlockDisplay(display);
_position.x = attrib.x;
_position.y = attrib.y;
@@ -837,6 +874,8 @@ static void intern_clipboard_atoms()
int i;
static bool interned = false;
if (interned) return;
+
+ XLockDisplay(x_display);
clipboard_prop = XInternAtom(x_display, "CLIPBOARD", False);
incr_atom = XInternAtom(x_display, "INCR", False);
multiple_atom = XInternAtom(x_display, "MULTIPLE", False);
@@ -844,6 +883,8 @@ static void intern_clipboard_atoms()
for(i = 0; i < utf8_atom_count; i++)
utf8_atoms[i] = XInternAtom(x_display, utf8_atom_names[i], False);
+ XUnlockDisplay(x_display);
+
interned = true;
}
@@ -856,7 +897,10 @@ DynamicScreen::DynamicScreen(Display* display, int screen, int& next_mon_id)
{
X_DEBUG_SYNC(display);
//FIXME: replace RootWindow() in other refs as well?
+ XLockDisplay(display);
platform_win = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, 1, 1, 0, 0, 0);
+ XUnlockDisplay(display);
+
LOG_INFO("platform_win: %u", (unsigned int)platform_win);
intern_clipboard_atoms();
XSelectInput(display, platform_win, StructureNotifyMask);
@@ -907,7 +951,10 @@ void DynamicScreen::do_set_mode(int width, int height)
int num_sizes;
X_DEBUG_SYNC(get_display());
+
+ XLockDisplay(get_display());
XRRScreenSize* sizes = XRRSizes(get_display(), get_screen(), &num_sizes);
+ XUnlockDisplay(get_display());
typedef std::set<SizeInfo, SizeCompare> SizesSet;
SizesSet sizes_set;
@@ -932,7 +979,10 @@ void DynamicScreen::do_restore()
}
int num_sizes;
+ XLockDisplay(get_display());
XRRScreenSize* sizes = XRRSizes(get_display(), get_screen(), &num_sizes);
+ XUnlockDisplay(get_display());
+
for (int i = 0; i < num_sizes; i++) {
if (sizes[i].width == _saved_width && sizes[i].height == _saved_height) {
set_screen_size(i);
@@ -949,7 +999,11 @@ bool DynamicScreen::set_screen_size(int size_index)
Window root_window = RootWindow(get_display(), get_screen());
XRRScreenConfiguration* config;
- if (!(config = XRRGetScreenInfo(get_display(), root_window))) {
+ XLockDisplay(get_display());
+ config = XRRGetScreenInfo(get_display(), root_window);
+ XUnlockDisplay(get_display());
+
+ if (!config) {
LOG_WARN("get screen info failed");
return false;
}
@@ -965,7 +1019,11 @@ bool DynamicScreen::set_screen_size(int size_index)
X_DEBUG_SYNC(get_display());
int num_sizes;
+
+ XLockDisplay(get_display());
XRRScreenSize* sizes = XRRSizes(get_display(), get_screen(), &num_sizes);
+ XUnlockDisplay(get_display());
+
if (num_sizes <= size_index) {
THROW("invalid sizes size");
}
@@ -1091,10 +1149,13 @@ MultyMonScreen::MultyMonScreen(Display* display, int screen, int& next_mon_id)
{
X_DEBUG_SYNC(get_display());
Window root_window = RootWindow(display, screen);
+
+ XLockDisplay(display);
XRRGetScreenSizeRange(display, root_window, &_min_width, &_min_height,
&_max_width, &_max_height);
-
AutoScreenRes res(XRRGetScreenResources(display, root_window));
+ XUnlockDisplay(display);
+
if (!res.valid()) {
THROW("get screen resources failed");
}
@@ -1102,6 +1163,7 @@ MultyMonScreen::MultyMonScreen(Display* display, int screen, int& next_mon_id)
#ifdef SHOW_SCREEN_INFO
show_scren_info();
#endif
+ XLockDisplay(display);
try {
for (int i = 0; i < res->ncrtc; i++) {
AutoCrtcInfo crtc_info(XRRGetCrtcInfo(display, res.get(), res->crtcs[i]));
@@ -1126,12 +1188,17 @@ MultyMonScreen::MultyMonScreen(Display* display, int screen, int& next_mon_id)
_monitors.push_back(new XMonitor(*this, next_mon_id++, res->crtcs[i]));
}
+ XUnlockDisplay(display);
} catch (...) {
+ XUnlockDisplay(display);
monitors_cleanup();
throw;
}
+ XLockDisplay(display);
platform_win = XCreateSimpleWindow(display, RootWindow(display, screen), 0, 0, 1, 1, 0, 0, 0);
+ XUnlockDisplay(display);
+
LOG_INFO("platform_win: %u", (unsigned int)platform_win);
intern_clipboard_atoms();
XSelectInput(display, platform_win, StructureNotifyMask);
@@ -1851,13 +1918,18 @@ void XMonitor::update_position()
Display* display = _container.get_display();
X_DEBUG_SYNC(display);
Window root_window = RootWindow(display, _container.get_screen());
+
+ XLockDisplay(display);
AutoScreenRes res(XRRGetScreenResources(display, root_window));
+ XUnlockDisplay(display);
if (!res.valid()) {
THROW("get screen resources failed");
}
+ XLockDisplay(display);
AutoCrtcInfo crtc_info(XRRGetCrtcInfo(display, res.get(), _crtc));
+ XUnlockDisplay(display);
ASSERT(crtc_info->noutput);
@@ -1887,7 +1959,9 @@ void XMonitor::update_position()
//todo: set valid subpixel order in case all outputs share the same type
_subpixel_order = RED_SUBPIXEL_ORDER_UNKNOWN;
} else {
+ XLockDisplay(display);
AutoOutputInfo output_info(XRRGetOutputInfo(display, res.get(), crtc_info->outputs[0]));
+ XUnlockDisplay(display);
switch (output_info->subpixel_order) {
case SubPixelUnknown:
@@ -1924,8 +1998,10 @@ void XMonitor::update_position()
bool XMonitor::finde_mode_in_outputs(RRMode mode, int start_index, XRRScreenResources* res)
{
int i, j;
+ bool retval = true;
X_DEBUG_SYNC(_container.get_display());
+ XLockDisplay(_container.get_display());
for (i = start_index; i < _noutput; i++) {
AutoOutputInfo output_info(XRRGetOutputInfo(_container.get_display(), res, _outputs[i]));
for (j = 0; j < output_info->nmode; j++) {
@@ -1934,11 +2010,13 @@ bool XMonitor::finde_mode_in_outputs(RRMode mode, int start_index, XRRScreenReso
}
}
if (j == output_info->nmode) {
- return false;
+ retval = false;
+ break;
}
}
+ XUnlockDisplay(_container.get_display());
X_DEBUG_SYNC(_container.get_display());
- return true;
+ return retval;
}
bool XMonitor::finde_mode_in_clones(RRMode mode, XRRScreenResources* res)
@@ -1975,7 +2053,11 @@ XRRModeInfo* XMonitor::find_mode(int width, int height, XRRScreenResources* res)
typedef std::set<ModeInfo, ModeCompare> ModesSet;
ModesSet modes_set;
X_DEBUG_SYNC(_container.get_display());
+
+ XLockDisplay(_container.get_display());
AutoOutputInfo output_info(XRRGetOutputInfo(_container.get_display(), res, _outputs[0]));
+ XUnlockDisplay(_container.get_display());
+
for (int i = 0; i < output_info->nmode; i++) {
XRRModeInfo* mode_inf = find_mod(res, output_info->modes[i]);
if (mode_inf->width >= width && mode_inf->height >= height) {
@@ -2010,7 +2092,11 @@ void XMonitor::do_set_mode(int width, int height)
Display* display = _container.get_display();
X_DEBUG_SYNC(display);
Window root_window = RootWindow(display, _container.get_screen());
+
+ XLockDisplay(display);
AutoScreenRes res(XRRGetScreenResources(display, root_window));
+ XUnlockDisplay(display);
+
if (!res.valid()) {
THROW("get screen resource failed");
}
@@ -2041,7 +2127,11 @@ void XMonitor::disable()
Display* display = _container.get_display();
X_DEBUG_SYNC(display);
Window root_window = RootWindow(display, _container.get_screen());
+
+ XLockDisplay(display);
AutoScreenRes res(XRRGetScreenResources(display, root_window));
+ XUnlockDisplay(display);
+
if (!res.valid()) {
THROW("get screen resources failed");
}
@@ -2061,7 +2151,11 @@ void XMonitor::enable()
Display* display = _container.get_display();
X_DEBUG_SYNC(display);
Window root_window = RootWindow(display, _container.get_screen());
+
+ XLockDisplay(display);
AutoScreenRes res(XRRGetScreenResources(display, root_window));
+ XUnlockDisplay(display);
+
if (!res.valid()) {
THROW("get screen resources failed");
}
@@ -2343,7 +2437,7 @@ static int get_selection(XEvent &event, Atom type, Atom prop, int format,
{
Bool del = incr ? True: False;
Atom type_ret;
- int format_ret, ret_val = -1;
+ int res, format_ret, ret_val = -1;
unsigned long len, remain;
unsigned char *data = NULL;
@@ -2366,9 +2460,15 @@ static int get_selection(XEvent &event, Atom type, Atom prop, int format,
}
}
- if (XGetWindowProperty(x_display, platform_win, prop, 0,
- LONG_MAX, del, type, &type_ret, &format_ret, &len,
- &remain, &data) != Success) {
+ /* Warning we are running with the clipboard_lock held!! That is ok, as
+ there is no code holding XLockDisplay which calls code taking
+ the clipboard_lock!! */
+ XLockDisplay(x_display);
+ res = XGetWindowProperty(x_display, platform_win, prop, 0,
+ LONG_MAX, del, type, &type_ret, &format_ret, &len,
+ &remain, &data);
+ XUnlockDisplay(x_display);
+ if (res != Success) {
LOG_WARN("XGetWindowProperty failed");
goto exit;
}
@@ -2686,17 +2786,25 @@ static void root_win_proc(XEvent& event)
static void process_monitor_configure_events(Window root)
{
- XSync(x_display, False);
XEvent event;
+ XLockDisplay(x_display);
+ XSync(x_display, False);
+
while (XCheckTypedWindowEvent(x_display, root, ConfigureNotify, &event)) {
+ XUnlockDisplay(x_display);
root_win_proc(event);
+ XLockDisplay(x_display);
}
while (XCheckTypedWindowEvent(x_display, root, xrandr_event_base + RRScreenChangeNotify,
&event)) {
+ XUnlockDisplay(x_display);
root_win_proc(event);
+ XLockDisplay(x_display);
}
+
+ XUnlockDisplay(x_display);
}
static void cleanup(void)
@@ -2779,7 +2887,7 @@ static void init_xfixes()
XFixesQueryVersion(x_display, &major, &minor) && major >= 1;
}
-unsigned int get_modifier_mask(KeySym modifier)
+static unsigned int get_modifier_mask(KeySym modifier)
{
int mask = 0;
int i;
@@ -3028,7 +3136,9 @@ uint32_t Platform::get_keyboard_lock_modifiers()
XKeyboardState keyboard_state;
uint32_t modifiers = 0;
+ XLockDisplay(x_display);
XGetKeyboardControl(x_display, &keyboard_state);
+ XUnlockDisplay(x_display);
if (keyboard_state.led_mask & 0x01) {
modifiers |= CAPS_LOCK_MODIFIER;
@@ -3088,7 +3198,7 @@ void Platform::set_keyboard_lock_modifiers(uint32_t modifiers)
}
}
-uint32_t key_bit(char* keymap, int key, uint32_t bit)
+static uint32_t key_bit(char* keymap, int key, uint32_t bit)
{
KeyCode key_code = XKeysymToKeycode(x_display, key);
return (((keymap[key_code >> 3] >> (key_code & 7)) & 1) ? bit : 0);
@@ -3097,14 +3207,19 @@ uint32_t key_bit(char* keymap, int key, uint32_t bit)
uint32_t Platform::get_keyboard_modifiers()
{
char keymap[32];
+ uint32_t mods;
+ XLockDisplay(x_display);
XQueryKeymap(x_display, keymap);
- return key_bit(keymap, XK_Shift_L, L_SHIFT_MODIFIER) |
+ mods = key_bit(keymap, XK_Shift_L, L_SHIFT_MODIFIER) |
key_bit(keymap, XK_Shift_R, R_SHIFT_MODIFIER) |
key_bit(keymap, XK_Control_L, L_CTRL_MODIFIER) |
key_bit(keymap, XK_Control_R, R_CTRL_MODIFIER) |
key_bit(keymap, XK_Alt_L, L_ALT_MODIFIER) |
key_bit(keymap, XK_Alt_R, R_ALT_MODIFIER);
+ XUnlockDisplay(x_display);
+
+ return mods;
}
void Platform::reset_cursor_pos()
@@ -3258,7 +3373,9 @@ XLocalCursor::XLocalCursor(CursorData* cursor_data)
case SPICE_CURSOR_TYPE_COLOR8:
default:
LOG_WARN("unsupported cursor type %d", header.type);
+ XLockDisplay(x_display);
_handle = XCreateFontCursor(x_display, XC_arrow);
+ XUnlockDisplay(x_display);
delete[] cur_data;
return;
}
@@ -3284,22 +3401,25 @@ XLocalCursor::XLocalCursor(CursorData* cursor_data)
}
Window root_window = RootWindow(x_display, DefaultScreen(x_display));
- Pixmap pixmap = XCreatePixmap(x_display, root_window, header.width, header.height, 32);
-
XGCValues gc_vals;
gc_vals.function = GXcopy;
gc_vals.foreground = ~0;
gc_vals.background = 0;
gc_vals.plane_mask = AllPlanes;
+ XLockDisplay(x_display);
+ Pixmap pixmap = XCreatePixmap(x_display, root_window, header.width, header.height, 32);
GC gc = XCreateGC(x_display, pixmap, GCFunction | GCForeground | GCBackground | GCPlaneMask,
&gc_vals);
+
XPutImage(x_display, pixmap, gc, &image, 0, 0, 0, 0, header.width, header.height);
XFreeGC(x_display, gc);
XRenderPictFormat *xformat = XRenderFindStandardFormat(x_display, PictStandardARGB32);
Picture picture = XRenderCreatePicture(x_display, pixmap, xformat, 0, NULL);
_handle = XRenderCreateCursor(x_display, picture, header.hot_spot_x, header.hot_spot_y);
+ XUnlockDisplay(x_display);
+
XRenderFreePicture(x_display, picture);
XFreePixmap(x_display, pixmap);
delete[] cur_data;
@@ -3323,7 +3443,12 @@ LocalCursor* Platform::create_inactive_cursor()
class XDefaultCursor: public XBaseLocalCursor {
public:
- XDefaultCursor() { _handle = XCreateFontCursor(x_display, XC_top_left_arrow);}
+ XDefaultCursor()
+ {
+ XLockDisplay(x_display);
+ _handle = XCreateFontCursor(x_display, XC_top_left_arrow);
+ XUnlockDisplay(x_display);
+ }
};
LocalCursor* Platform::create_default_cursor()
@@ -3440,13 +3565,17 @@ bool Platform::on_clipboard_notify(uint32_t type, const uint8_t* data, int32_t s
bool Platform::on_clipboard_request(uint32_t type)
{
+ Window owner;
Lock lock(clipboard_lock);
Atom target = get_clipboard_target(type);
if (target == None)
return false;
- if (XGetSelectionOwner(x_display, clipboard_prop) == None) {
+ XLockDisplay(x_display);
+ owner = XGetSelectionOwner(x_display, clipboard_prop);
+ XUnlockDisplay(x_display);
+ if (owner == None) {
LOG_INFO("No owner for the selection");
return false;
}
@@ -3464,8 +3593,12 @@ bool Platform::on_clipboard_request(uint32_t type)
void Platform::on_clipboard_release()
{
XEvent event;
+ Window owner;
- if (XGetSelectionOwner(x_display, clipboard_prop) != platform_win) {
+ XLockDisplay(x_display);
+ owner = XGetSelectionOwner(x_display, clipboard_prop);
+ XUnlockDisplay(x_display);
+ if (owner != platform_win) {
LOG_INFO("Platform::on_clipboard_release() called while not selection owner");
return;
}
@@ -3477,11 +3610,16 @@ void Platform::on_clipboard_release()
/* Make sure we process the XFixesSetSelectionOwnerNotify event caused
by this, so we don't end up changing the clipboard owner to none, after
it has already been re-owned because this event is still pending. */
+ XLockDisplay(x_display);
XSync(x_display, False);
while (XCheckTypedEvent(x_display,
XFixesSelectionNotify + xfixes_event_base,
- &event))
+ &event)) {
+ XUnlockDisplay(x_display);
root_win_proc(event);
+ XLockDisplay(x_display);
+ }
+ XUnlockDisplay(x_display);
/* Note no need to do a set_clipboard_owner(owner_none) here, as that is
already done by processing the XFixesSetSelectionOwnerNotify event. */
diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp
index 327028b9..e7151eda 100644
--- a/client/x11/red_drawable.cpp
+++ b/client/x11/red_drawable.cpp
@@ -216,7 +216,6 @@ static inline void copy_to_drawable_from_pixmap(const RedDrawable_p* dest,
dest->source.x_drawable.gc, source->pixmap.x_image,
src_x, src_y, area.left + offset.x, area.top + offset.y,
area.right - area.left, area.bottom - area.top, false);
- XSync(XPlatform::get_display(), 0);
} else {
XPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
dest->source.x_drawable.gc, source->pixmap.x_image, src_x,
@@ -242,7 +241,6 @@ static inline void copy_to_drawable_from_pixmap(const RedDrawable_p* dest,
dest->source.x_drawable.gc, image,
0, 0, area.left + offset.x, area.top + offset.y,
area.right - area.left, area.bottom - area.top, false);
- XSync(XPlatform::get_display(), 0);
} else {
XPutImage(XPlatform::get_display(), dest->source.x_drawable.drawable,
dest->source.x_drawable.gc, image,
@@ -252,6 +250,7 @@ static inline void copy_to_drawable_from_pixmap(const RedDrawable_p* dest,
free_temp_image(image, shminfo, pixman_image);
}
+ XFlush(XPlatform::get_display());
}
static inline void copy_to_x_drawable(const RedDrawable_p* dest,
@@ -628,6 +627,7 @@ static inline void fill_drawable(RedDrawable_p* dest, const SpiceRect& area, rgb
Drawable drawable = dest->source.x_drawable.drawable;
GC gc = dest->source.x_drawable.gc;
+ XLockDisplay(XPlatform::get_display());
Colormap color_map = DefaultColormap(XPlatform::get_display(),
DefaultScreen(XPlatform::get_display()));
XColor x_color;
@@ -639,6 +639,7 @@ static inline void fill_drawable(RedDrawable_p* dest, const SpiceRect& area, rgb
if (!XAllocColor(XPlatform::get_display(), color_map, &x_color)) {
LOG_WARN("color map failed");
}
+ XUnlockDisplay(XPlatform::get_display());
XGCValues gc_vals;
gc_vals.foreground = x_color.pixel;
@@ -724,6 +725,7 @@ static inline void frame_drawable(RedDrawable_p* dest, const SpiceRect& area, rg
Drawable drawable = dest->source.x_drawable.drawable;
GC gc = dest->source.x_drawable.gc;
+ XLockDisplay(XPlatform::get_display());
Colormap color_map = DefaultColormap(XPlatform::get_display(),
DefaultScreen(XPlatform::get_display()));
XColor x_color;
@@ -735,6 +737,7 @@ static inline void frame_drawable(RedDrawable_p* dest, const SpiceRect& area, rg
if (!XAllocColor(XPlatform::get_display(), color_map, &x_color)) {
LOG_WARN("color map failed");
}
+ XUnlockDisplay(XPlatform::get_display());
XGCValues gc_vals;
gc_vals.foreground = x_color.pixel;
diff --git a/client/x11/red_window.cpp b/client/x11/red_window.cpp
index 5a0886ac..e7b68151 100644
--- a/client/x11/red_window.cpp
+++ b/client/x11/red_window.cpp
@@ -309,13 +309,17 @@ enum KbdKeyCode {
static void query_keyboard()
{
+ XLockDisplay(x_display);
XkbDescPtr kbd_desk = XkbGetKeyboard(x_display, XkbAllComponentsMask, XkbUseCoreKbd);
+ XUnlockDisplay(x_display);
if (!kbd_desk) {
LOG_WARN("get keyboard failed");
return;
}
+ XLockDisplay(x_display);
char* keycodes = XGetAtomName(x_display, kbd_desk->names->keycodes);
+ XUnlockDisplay(x_display);
if (keycodes) {
if (strstr(keycodes, "evdev")) {
@@ -642,7 +646,9 @@ static void init_key_table_0xfe()
static inline RedKey to_red_key_code(unsigned int keycode)
{
+ XLockDisplay(x_display);
KeySym sym = XKeycodeToKeysym(x_display, keycode, 0);
+ XUnlockDisplay(x_display);
RedKey red_key;
if (sym == NoSymbol) {
@@ -772,8 +778,12 @@ void RedWindow_p::win_proc(XEvent& event)
{
XPointer window_pointer;
RedWindow* red_window;
+ int res;
- if (XFindContext(x_display, event.xany.window, user_data_context, &window_pointer)) {
+ XLockDisplay(x_display);
+ res = XFindContext(x_display, event.xany.window, user_data_context, &window_pointer);
+ XUnlockDisplay(x_display);
+ if (res) {
THROW("no user data");
}
red_window = (RedWindow*)window_pointer;
@@ -795,7 +805,10 @@ void RedWindow_p::win_proc(XEvent& event)
case KeyRelease: {
RedKey key = to_red_key_code(event.xkey.keycode);
XEvent next_event;
- if (XCheckWindowEvent(x_display, red_window->_win, ~long(0), &next_event)) {
+ XLockDisplay(x_display);
+ Bool check = XCheckWindowEvent(x_display, red_window->_win, ~long(0), &next_event);
+ XUnlockDisplay(x_display);
+ if (check) {
XPutBackEvent(x_display, &next_event);
if ((next_event.type == KeyPress) &&
(event.xkey.keycode == next_event.xkey.keycode) &&
@@ -921,6 +934,8 @@ void RedWindow_p::win_proc(XEvent& event)
void RedWindow_p::sync(bool shadowed)
{
+ XEvent event;
+
if (shadowed) {
_ignore_foucs = true;
_ignore_pointer = true;
@@ -928,11 +943,16 @@ void RedWindow_p::sync(bool shadowed)
_shadow_pointer_state = _pointer_in_window;
_shadow_focus_event.xany.serial = 0;
}
+
+ XLockDisplay(x_display);
XSync(x_display, False);
- XEvent event;
while (XCheckWindowEvent(x_display, _win, ~long(0), &event)) {
+ XUnlockDisplay(x_display);
win_proc(event);
+ XLockDisplay(x_display);
}
+ XUnlockDisplay(x_display);
+
if (!shadowed) {
return;
}
@@ -954,11 +974,17 @@ void RedWindow_p::wait_for_reparent()
{
XEvent event;
for (int i = 0; i < 50; i++) {
- if (XCheckTypedWindowEvent(x_display, _win, ReparentNotify, &event)) {
+ XLockDisplay(x_display);
+ bool check = XCheckTypedWindowEvent(x_display, _win, ReparentNotify, &event);
+ XUnlockDisplay(x_display);
+ if (check) {
return;
}
usleep(20 * 1000);
+ // HDG: why?? this makes no sense
+ XLockDisplay(x_display);
XSync(x_display, False);
+ XUnlockDisplay(x_display);
}
DBG(0, "failed");
}
@@ -968,7 +994,9 @@ void RedWindow_p::wait_for_map()
bool wait_parent = _expect_parent;
while (!_visibale) {
XEvent event;
+ XLockDisplay(x_display);
XWindowEvent(x_display, _win, ~0, &event);
+ XUnlockDisplay(x_display);
switch (event.type) {
case ReparentNotify:
wait_parent = false;
@@ -993,7 +1021,9 @@ void RedWindow_p::wait_for_unmap()
bool wait_parent = _expect_parent;
while (_visibale) {
XEvent event;
+ XLockDisplay(x_display);
XWindowEvent(x_display, _win, ~0, &event);
+ XUnlockDisplay(x_display);
switch (event.type) {
case ReparentNotify:
wait_parent = false;
@@ -1015,7 +1045,9 @@ void RedWindow_p::wait_for_unmap()
void RedWindow_p::set_glx(int width, int height)
{
if (_glcont_copy) {
+ XLockDisplay(x_display);
XSync(x_display, False);
+ XUnlockDisplay(x_display);
glXMakeCurrent(x_display, _win, _glcont_copy);
//glDrawBuffer(GL_FRONT);
glMatrixMode(GL_PROJECTION);
@@ -1050,8 +1082,10 @@ Cursor RedWindow_p::create_invisible_cursor(Window window)
XColor color;
char data[1] = {0};
Window root_window = RootWindow(x_display, DefaultScreen(x_display));
+ XLockDisplay(x_display);
Pixmap blank = XCreateBitmapFromData(x_display, root_window, data, 1, 1);
Cursor cursor = XCreatePixmapCursor(x_display, blank, blank, &color, &color, 0, 0);
+ XUnlockDisplay(x_display);
XFreePixmap(x_display, blank);
return cursor;
}
@@ -1071,6 +1105,8 @@ RedWindow_p::RedWindow_p()
void RedWindow_p::destroy(RedWindow& red_window, PixelsSource_p& pix_source)
{
+ XEvent event;
+
if (_win == None) {
return;
}
@@ -1082,9 +1118,12 @@ void RedWindow_p::destroy(RedWindow& red_window, PixelsSource_p& pix_source)
XPlatform::cleare_win_proc(_win);
XSelectInput(x_display, _win, 0);
+
+ XLockDisplay(x_display);
XSync(x_display, False);
- XEvent event;
while (XCheckWindowEvent(x_display, _win, ~long(0), &event));
+ XUnlockDisplay(x_display);
+
Window window = _win;
_win = None;
XFreeCursor(x_display, _invisible_cursor);
@@ -1123,6 +1162,7 @@ void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int
ButtonReleaseMask | PointerMotionMask | FocusChangeMask |
EnterWindowMask | LeaveWindowMask;
+ XLockDisplay(x_display);
_colormap = XCreateColormap(x_display, root_window, XPlatform::get_vinfo()[in_screen]->visual,
AllocNone);
win_attributes.colormap = _colormap;
@@ -1131,22 +1171,34 @@ void RedWindow_p::create(RedWindow& red_window, PixelsSource_p& pix_source, int
width, height, 0, XPlatform::get_vinfo()[in_screen]->depth,
InputOutput, XPlatform::get_vinfo()[in_screen]->visual, mask,
&win_attributes);
+ XUnlockDisplay(x_display);
if (!window) {
THROW("create X window failed");
}
try {
- if (XSaveContext(x_display, window, user_data_context, (XPointer)&red_window)) {
+ int res;
+
+ XLockDisplay(x_display);
+ res = XSaveContext(x_display, window, user_data_context, (XPointer)&red_window);
+ XUnlockDisplay(x_display);
+ if (res) {
THROW("set win usr data failed");
}
XSetWMProtocols(x_display, window, &wm_delete_window_atom, 1);
XGCValues gc_vals;
- if (!(gc = XCreateGC(x_display, window, 0, &gc_vals))) {
+
+ XLockDisplay(x_display);
+ gc = XCreateGC(x_display, window, 0, &gc_vals);
+ XUnlockDisplay(x_display);
+ if (!gc) {
THROW("create gc failed");
}
- if (!(cursor = create_invisible_cursor(window))) {
+
+ cursor = create_invisible_cursor(window);
+ if (!cursor) {
THROW("create invisible cursor failed");
}
@@ -1189,7 +1241,9 @@ void RedWindow_p::migrate(RedWindow& red_window, PixelsSource_p& pix_source, int
THROW("get attributes failed");
}
XTextProperty text_pro;
+ XLockDisplay(x_display);
bool valid_title = XGetWMName(x_display, _win, &text_pro) && text_pro.value;
+ XUnlockDisplay(x_display);
destroy(red_window, pix_source);
create(red_window, pix_source, _show_pos.x, _show_pos.y, attrib.width, attrib.height,
to_screen);
@@ -1213,6 +1267,7 @@ void RedWindow_p::move_to_current_desktop()
unsigned char *prop_return;
long desktop = ~long(0);
+ XLockDisplay(x_display);
if (XGetWindowProperty(x_display, root, wm_current_desktop, 0, 1, False, AnyPropertyType,
&actual_type_return, &actual_format_return, &nitems_return,
&bytes_after_return, &prop_return) == Success &&
@@ -1221,6 +1276,7 @@ void RedWindow_p::move_to_current_desktop()
} else {
DBG(0, "get current desktop failed");
}
+ XUnlockDisplay(x_display);
XEvent xevent;
xevent.type = ClientMessage;
@@ -1266,7 +1322,9 @@ void RedWindow::set_title(std::wstring& title)
wchar_t *name = const_cast<wchar_t *>(title.c_str());
int r;
if (_win) {
+ XLockDisplay(x_display);
r = XwcTextListToTextProperty(x_display, &name, 1, XStringStyle, &text_prop);
+ XUnlockDisplay(x_display);
if (r >= 0) {
XSetWMName(x_display, _win, &text_prop);
XFree(text_prop.value);
@@ -1323,15 +1381,19 @@ public:
AutoXErrorHandler()
{
ASSERT(old_error_handler == NULL);
+ XLockDisplay(x_display);
XSync(x_display, False);
x_error = Success;
old_error_handler = XSetErrorHandler(x_error_handler);
+ XUnlockDisplay(x_display);
}
~AutoXErrorHandler()
{
if (old_error_handler) {
+ XLockDisplay(x_display);
XSetErrorHandler(old_error_handler);
+ XUnlockDisplay(x_display);
old_error_handler = NULL;
}
}
@@ -1344,8 +1406,12 @@ static Window get_window_for_reposition(Window window)
Window parent;
Window* childrens;
unsigned int num_childrens;
+ int res;
- if (!XQueryTree(x_display, window, &root, &parent, &childrens, &num_childrens)) {
+ XLockDisplay(x_display);
+ res = XQueryTree(x_display, window, &root, &parent, &childrens, &num_childrens);
+ XUnlockDisplay(x_display);
+ if (!res) {
return None;
}
@@ -1464,7 +1530,9 @@ static bool get_prop_32(Window win, Atom prop, uint32_t &val)
unsigned long bytes_after_return;
unsigned long nitems_return;
unsigned char *prop_return;
+ bool retval = false;
+ XLockDisplay(x_display);
if (XGetWindowProperty(x_display, win, prop, 0, 1, False, AnyPropertyType,
&actual_type_return, &actual_format_return,
&nitems_return, &bytes_after_return, &prop_return) == Success &&
@@ -1472,9 +1540,11 @@ static bool get_prop_32(Window win, Atom prop, uint32_t &val)
actual_type_return != None &&
actual_format_return == 32) {
val = *(uint32_t *)prop_return;
- return true;
+ retval = true;
}
- return false;
+ XUnlockDisplay(x_display);
+
+ return retval;
}
void RedWindow::external_show()
@@ -1486,7 +1556,9 @@ void RedWindow::external_show()
raise();
activate();
+ XLockDisplay(x_display);
atom = XInternAtom(x_display, "_NET_ACTIVE_WINDOW", true);
+ XUnlockDisplay(x_display);
if (atom != None) {
Window root;
XEvent xev;
@@ -1595,14 +1667,21 @@ static bool __get_position(Window window, SpicePoint& pos)
Window parent;
Window* childrens;
unsigned int num_childrens;
+ int res;
- if (!XGetWindowAttributes(x_display, window, &attrib)) {
+ XLockDisplay(x_display);
+ res = XGetWindowAttributes(x_display, window, &attrib);
+ XUnlockDisplay(x_display);
+ if (!res) {
return false;
}
pos.x += attrib.x;
pos.y += attrib.y;
- if (!XQueryTree(x_display, window, &root, &parent, &childrens, &num_childrens)) {
+ XLockDisplay(x_display);
+ res = XQueryTree(x_display, window, &root, &parent, &childrens, &num_childrens);
+ XUnlockDisplay(x_display);
+ if (!res) {
return false;
}
@@ -1648,7 +1727,9 @@ void RedWindow::do_start_key_interception()
// LeaveNotify and EnterNotify.
ASSERT(_focused);
+ XLockDisplay(x_display);
XGrabKeyboard(x_display, _win, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ XUnlockDisplay(x_display);
sync(true);
_listener.on_start_key_interception();
_key_interception_on = true;
@@ -1656,7 +1737,9 @@ void RedWindow::do_start_key_interception()
void RedWindow::do_stop_key_interception()
{
+ XLockDisplay(x_display);
XUngrabKeyboard(x_display, CurrentTime);
+ XUnlockDisplay(x_display);
sync(true);
_key_interception_on = false;
_listener.on_stop_key_interception();
@@ -1715,18 +1798,24 @@ void RedWindow::hide_cursor()
void RedWindow::release_mouse()
{
+ XLockDisplay(x_display);
XUngrabPointer(x_display, CurrentTime);
+ XUnlockDisplay(x_display);
sync(true);
}
void RedWindow::cupture_mouse()
{
int grab_retries = MOUSE_GRAB_RETRIES;
+ XLockDisplay(x_display);
XSync(x_display, False);
+ XUnlockDisplay(x_display);
for (;; --grab_retries) {
+ XLockDisplay(x_display);
int result = XGrabPointer(x_display, _win, True, 0,
GrabModeAsync, GrabModeAsync,
_win, None, CurrentTime);
+ XUnlockDisplay(x_display);
if (result == GrabSuccess) {
break;
}
@@ -1748,7 +1837,9 @@ void RedWindow::set_mouse_position(int x, int y)
SpicePoint RedWindow::get_size()
{
XWindowAttributes attrib;
+ XLockDisplay(x_display);
XGetWindowAttributes(x_display, _win, &attrib);
+ XUnlockDisplay(x_display);
SpicePoint size;
size.x = attrib.width;
size.y = attrib.height;
@@ -1777,7 +1868,12 @@ static QRegion *get_visibale_region(Window window)
QRegion* region = new QRegion;
region_init(region);
XWindowAttributes attrib;
- if (!XGetWindowAttributes(x_display, window, &attrib)) {
+ int res;
+
+ XLockDisplay(x_display);
+ res = XGetWindowAttributes(x_display, window, &attrib);
+ XUnlockDisplay(x_display);
+ if (!res) {
return NULL;
}
@@ -1800,11 +1896,20 @@ static QRegion *get_visibale_region(Window window)
AutoXErrorHandler auto_error_handler;
for (;;) {
- FAIL_ON_BAD_WINDOW(!XQueryTree(x_display, window, &root, &parent, &childrens,
- &num_childrens),
+ int res;
+
+ XLockDisplay(x_display);
+ res = XQueryTree(x_display, window, &root, &parent, &childrens,
+ &num_childrens);
+ XUnlockDisplay(x_display);
+ FAIL_ON_BAD_WINDOW(!res,
"%s: query X tree failed", __FUNCTION__);
for (int i = num_childrens - 1; i >= 0 && childrens[i] != prev; i--) {
- FAIL_ON_BAD_WINDOW(!XGetWindowAttributes(x_display, childrens[i], &attrib),
+
+ XLockDisplay(x_display);
+ res = XGetWindowAttributes(x_display, childrens[i], &attrib);
+ XUnlockDisplay(x_display);
+ FAIL_ON_BAD_WINDOW(!res,
"%s: get win attributes failed", __FUNCTION__);
if (attrib.map_state == IsViewable) {
@@ -1821,7 +1926,10 @@ static QRegion *get_visibale_region(Window window)
XFree(childrens);
}
- FAIL_ON_BAD_WINDOW(!XGetWindowAttributes(x_display, window, &attrib),
+ XLockDisplay(x_display);
+ res = XGetWindowAttributes(x_display, window, &attrib);
+ XUnlockDisplay(x_display);
+ FAIL_ON_BAD_WINDOW(!res,
"%s: get win attributes failed", __FUNCTION__);
window_area_from_attributes(window_area, attrib);
region_offset(region, window_area.left, window_area.top);
@@ -1830,7 +1938,10 @@ static QRegion *get_visibale_region(Window window)
break;
}
- FAIL_ON_BAD_WINDOW(!XGetWindowAttributes(x_display, parent, &attrib),
+ XLockDisplay(x_display);
+ res = XGetWindowAttributes(x_display, parent, &attrib);
+ XUnlockDisplay(x_display);
+ FAIL_ON_BAD_WINDOW(!res,
"%s: get win attributes failed", __FUNCTION__);
window_area_from_attributes(window_area, attrib);
window_area.right -= window_area.left;
@@ -1907,10 +2018,13 @@ bool RedWindow::get_mouse_anchor_point(SpicePoint& pt)
#ifdef USE_OGL
RedGlContext RedWindow::create_context_gl()
{
+ RedGlContext *context = NULL;
if (XPlatform::get_fbconfig()[_screen]) {
- return glXCreateContext(x_display, XPlatform::get_vinfo()[_screen], NULL, GL_TRUE);
+ XLockDisplay(x_display);
+ context = glXCreateContext(x_display, XPlatform::get_vinfo()[_screen], NULL, GL_TRUE);
+ XUnlockDisplay(x_display);
}
- return NULL;
+ return context;
}
RedPbuffer RedWindow::create_pbuff(int width, int height)
@@ -1925,8 +2039,10 @@ RedPbuffer RedWindow::create_pbuff(int width, int height)
0, 0 };
fb_config = XPlatform::get_fbconfig();
+ XLockDisplay(XPlatform::get_display());
pbuff = glXCreatePbuffer(XPlatform::get_display(), fb_config[_screen][0],
pbuf_attr);
+ XUnlockDisplay(XPlatform::get_display());
return pbuff;
}
diff --git a/client/x11/x_icon.cpp b/client/x11/x_icon.cpp
index e59a030d..937eecc2 100644
--- a/client/x11/x_icon.cpp
+++ b/client/x11/x_icon.cpp
@@ -61,13 +61,19 @@ void XIcon::get_pixmaps(int screen, Pixmap& out_pixmap, Pixmap& out_mask)
Pixmap mask = None;
GC gc = NULL;
try {
+ XLockDisplay(x_display);
pixmap = XCreatePixmap(x_display, root_window, _raw_icon->width, _raw_icon->height, 24);
+ XUnlockDisplay(x_display);
if (pixmap == None) {
THROW("create pixmap failed");
}
XWindowAttributes attr;
+
+ XLockDisplay(x_display);
XGetWindowAttributes(x_display, root_window, &attr);
+ XUnlockDisplay(x_display);
+
XImage image;
memset(&image, 0, sizeof(image));
image.width = _raw_icon->width;
@@ -94,14 +100,18 @@ void XIcon::get_pixmaps(int screen, Pixmap& out_pixmap, Pixmap& out_mask)
gc_vals.foreground = ~0;
gc_vals.background = 0;
gc_vals.plane_mask = AllPlanes;
+
+ XLockDisplay(x_display);
gc = XCreateGC(x_display, pixmap, GCFunction | GCForeground | GCBackground | GCPlaneMask,
&gc_vals);
XPutImage(x_display, pixmap, gc, &image, 0, 0, 0, 0, image.width, image.height);
+ // HDG: why ?? XFlush should suffice
XSync(x_display, False);
XFreeGC(x_display, gc);
gc = NULL;
mask = XCreatePixmap(x_display, root_window, _raw_icon->width, _raw_icon->height, 1);
+ XUnlockDisplay(x_display);
if (mask == None) {
THROW("create mask failed");
}
@@ -121,10 +131,13 @@ void XIcon::get_pixmaps(int screen, Pixmap& out_pixmap, Pixmap& out_mask)
THROW("init image failed");
}
+ XLockDisplay(x_display);
gc = XCreateGC(x_display, mask, GCFunction | GCForeground | GCBackground | GCPlaneMask,
&gc_vals);
XPutImage(x_display, mask, gc, &image, 0, 0, 0, 0, image.width, image.height);
+ // HDG: why ?? XFlush should suffice
XSync(x_display, False);
+ XUnlockDisplay(x_display);
XFreeGC(x_display, gc);
} catch (...) {
if (gc) {