diff options
-rw-r--r-- | client/x11/platform.cpp | 180 | ||||
-rw-r--r-- | client/x11/red_drawable.cpp | 7 | ||||
-rw-r--r-- | client/x11/red_window.cpp | 158 | ||||
-rw-r--r-- | client/x11/x_icon.cpp | 13 |
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) { |