--Boundary-00=_zkw7EB9ZV3KrcMT Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline Hello, I'm considering adding this optimization to kdelibs but first I'd need more testing for it, as it uses some kind of internal code of Xlib and I have no idea how it compiles/works on other platforms. Are there still people using KDE with some other X than X.org/XFree86? Could you please try if kdelibs with this patch compiles and works? As for technical details, each XGetWindowProperty() call for reading one X property means one X server roundtrip, i.e. sending request to X server and waiting for an answer (and the context switches and possibly transferring over network and so on). The patch allows grouping of such requests resulting in only one roundtrip for the whole group. It doesn't actually save as much as I originally expected, but I guess it could be still worth adding it, at least for people running remote X (well, since I've already written it anyway). Thanks -- Lubos Lunak KDE developer -------------------------------------------------------------- SUSE LINUX, s.r.o. e-mail: l.lunak@suse.cz , l.lunak@kde.org Lihovarska 1060/12 tel: +420 284 028 972 190 00 Prague 9 fax: +420 284 028 951 Czech Republic http//www.suse.cz --Boundary-00=_zkw7EB9ZV3KrcMT Content-Type: text/x-diff; charset="us-ascii"; name="kdecore.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="kdecore.patch" --- kdecore/kasyncprop.h.sav 2006-08-16 11:52:32.000000000 +0200 +++ kdecore/kasyncprop.h 2006-08-16 13:29:56.000000000 +0200 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 1986, 1998 The Open Group + * Copyright (C) 2002 Havoc Pennington + * Copyright (C) 2006 Lubos Lunak + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation. + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of The Open Group shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from The Open Group. + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void KXAskWindowProperty( Display *dpy, Window w, Atom property, long offset, + long length, Bool del, Atom req_type ); + +int KXReceiveWindowProperty( Display *dpy, Window w, Atom property, long offset, + long length, Bool del, Atom req_type, Atom *actual_type, int *actual_format, + unsigned long *nitems, unsigned long *bytesafter, unsigned char **prop ); + +void KXPropertyCleanup( Display* dpy ); + +#ifdef __cplusplus +} +#endif --- kdecore/Makefile.am.sav 2006-07-12 17:54:24.000000000 +0200 +++ kdecore/Makefile.am 2006-08-16 11:52:41.000000000 +0200 @@ -59,7 +59,7 @@ include_HEADERS = kconfig.h kconfigskele kcalendarsystem.h kcalendarsystemfactory.h kmacroexpander.h \ kmanagerselection.h kmountpoint.h kuser.h klockfile.h \ kidna.h ktempdir.h kshell.h fixx11h.h kxerrorhandler.h kdelibs_export.h \ - kdemacros.h kde_file.h ktimezones.h + kdemacros.h kde_file.h ktimezones.h kasyncprop.h libkdefakes_la_SOURCES = fakes.c vsnprintf.c libkdefakes_la_LDFLAGS = -version-info 6:0:2 @@ -113,7 +113,7 @@ libkdecore_la_SOURCES = libintl.cpp kapp ktempdir.cpp kshell.cpp kmountpoint.cpp kcalendarsystemjalali.cpp \ kprotocolinfo_kdecore.cpp kprotocolinfofactory.cpp kxerrorhandler.cpp \ kuser.cpp kconfigskeleton.cpp kconfigdialogmanager.cpp klockfile.cpp \ - kqiodevicegzip_p.cpp ktimezones.cpp + kqiodevicegzip_p.cpp ktimezones.cpp kasyncprop.c libkdecore_la_LDFLAGS = $(QT_LDFLAGS) $(KDE_RPATH) $(KDE_MT_LDFLAGS) $(X_LDFLAGS) $(USER_LDFLAGS) -version-info 6:0:2 -no-undefined libkdecore_la_LIBADD = malloc/libklmalloc.la network/libkdecorenetwork.la $(SVGICON_LIB) ../dcop/libDCOP.la ../libltdl/libltdlc.la $(LIB_XEXT) $(LIBRESOLV) $(LIBUTIL) $(LIBART_LIBS) $(LIB_IDN) ../kdefx/libkdefx.la --- kdecore/netwm.cpp.sav 2006-07-31 16:39:20.000000000 +0200 +++ kdecore/netwm.cpp 2006-08-16 15:14:30.000000000 +0200 @@ -39,6 +39,8 @@ #include "netwm_p.h" +#include + // UTF-8 string static Atom UTF8_STRING = 0; @@ -430,7 +432,8 @@ static void create_atoms(Display *d) { } -static void readIcon(Display* display, Window window, Atom property, NETRArray& icons, int& icon_count) { +static void readIcon(Display* display, Window window, Atom property, + NETRArray& icons, int& icon_count, bool has_prefetch) { #ifdef NETWMDEBUG fprintf(stderr, "NET: readIcon\n"); @@ -455,10 +458,17 @@ static void readIcon(Display* display, W // read data do { - if (XGetWindowProperty(display, window, property, offset, + int status; + if( has_prefetch ) + status = KXReceiveWindowProperty(display, window, property, offset, MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret, - &format_ret, &nitems_ret, &after_ret, &data_ret) - == Success) { + &format_ret, &nitems_ret, &after_ret, &data_ret); + else + status = XGetWindowProperty(display, window, property, offset, + MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret, + &format_ret, &nitems_ret, &after_ret, &data_ret); + has_prefetch = false; + if( status == Success) { if (!bufsize) { if (nitems_ret < 3 || type_ret != XA_CARDINAL || @@ -2104,11 +2114,64 @@ void NETRootInfo::update( const unsigned const unsigned long& dirty = props[ PROTOCOLS ]; const unsigned long& dirty2 = props[ PROTOCOLS2 ]; +// Property prefetching part. Duplicate calls to KXReceiveWindowProperty() +// as KXAskWindowProperty() calls here, without the out arguments. + if (dirty & Supported ) + KXAskWindowProperty(p->display, p->root, net_supported, + 0l, MAX_PROP_SIZE, False, XA_ATOM); + if (dirty & ClientList) + KXAskWindowProperty(p->display, p->root, net_client_list, + 0l, MAX_PROP_SIZE, False, XA_WINDOW); + if (dirty & KDESystemTrayWindows) + KXAskWindowProperty(p->display, p->root, kde_net_system_tray_windows, + 0l, MAX_PROP_SIZE, False, XA_WINDOW); + if (dirty & ClientListStacking) + KXAskWindowProperty(p->display, p->root, net_client_list_stacking, + 0, MAX_PROP_SIZE, False, XA_WINDOW); + if (dirty & NumberOfDesktops) + KXAskWindowProperty(p->display, p->root, net_number_of_desktops, + 0l, 1l, False, XA_CARDINAL); + if (dirty & DesktopGeometry) + KXAskWindowProperty(p->display, p->root, net_desktop_geometry, + 0l, 2l, False, XA_CARDINAL); + if (dirty & DesktopViewport) + KXAskWindowProperty(p->display, p->root, net_desktop_viewport, + 0l, 2l, False, XA_CARDINAL); + if (dirty & CurrentDesktop) + KXAskWindowProperty(p->display, p->root, net_current_desktop, + 0l, 1l, False, XA_CARDINAL); + if (dirty & DesktopNames) + KXAskWindowProperty(p->display, p->root, net_desktop_names, + 0l, MAX_PROP_SIZE, False, UTF8_STRING); + if (dirty & ActiveWindow) + KXAskWindowProperty(p->display, p->root, net_active_window, 0l, 1l, + False, XA_WINDOW); + if (dirty & WorkArea) + KXAskWindowProperty(p->display, p->root, net_workarea, 0l, + MAX_PROP_SIZE, False, XA_CARDINAL); + if (dirty & SupportingWMCheck) { + KXAskWindowProperty(p->display, p->root, net_supporting_wm_check, + 0l, 1l, False, XA_WINDOW); + // always prefetch the second property too, it will be made sure the reply + // is always read and freed + KXAskWindowProperty(p->display, p->supportwindow, + net_wm_name, 0l, MAX_PROP_SIZE, False, + UTF8_STRING); + } + if (dirty & VirtualRoots) + KXAskWindowProperty(p->display, p->root, net_virtual_roots, + 0, MAX_PROP_SIZE, False, XA_WINDOW); + if (dirty2 & WM2ShowingDesktop) + KXAskWindowProperty(p->display, p->root, net_showing_desktop, + 0, MAX_PROP_SIZE, False, XA_CARDINAL); + +// The fetching part - when you update KXReceiveWindowProperty() calls here, +// update also the XAskWindowProperty() calls. if (dirty & Supported ) { // only in Client mode for( int i = 0; i < PROPERTIES_SIZE; ++i ) p->properties[ i ] = 0; - if( XGetWindowProperty(p->display, p->root, net_supported, + if( KXReceiveWindowProperty(p->display, p->root, net_supported, 0l, MAX_PROP_SIZE, False, XA_ATOM, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success ) { @@ -2126,7 +2189,7 @@ void NETRootInfo::update( const unsigned if (dirty & ClientList) { bool read_ok = false; - if (XGetWindowProperty(p->display, p->root, net_client_list, + if (KXReceiveWindowProperty(p->display, p->root, net_client_list, 0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2197,7 +2260,7 @@ void NETRootInfo::update( const unsigned if (dirty & KDESystemTrayWindows) { bool read_ok = false; - if (XGetWindowProperty(p->display, p->root, kde_net_system_tray_windows, + if (KXReceiveWindowProperty(p->display, p->root, kde_net_system_tray_windows, 0l, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2262,7 +2325,7 @@ void NETRootInfo::update( const unsigned p->stacking_count = 0; delete[] p->stacking; p->stacking = NULL; - if (XGetWindowProperty(p->display, p->root, net_client_list_stacking, + if (KXReceiveWindowProperty(p->display, p->root, net_client_list_stacking, 0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2286,7 +2349,7 @@ void NETRootInfo::update( const unsigned if (dirty & NumberOfDesktops) { p->number_of_desktops = 0; - if (XGetWindowProperty(p->display, p->root, net_number_of_desktops, + if (KXReceiveWindowProperty(p->display, p->root, net_number_of_desktops, 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2305,7 +2368,7 @@ void NETRootInfo::update( const unsigned if (dirty & DesktopGeometry) { p->geometry = p->rootSize; - if (XGetWindowProperty(p->display, p->root, net_desktop_geometry, + if (KXReceiveWindowProperty(p->display, p->root, net_desktop_geometry, 0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2328,7 +2391,7 @@ void NETRootInfo::update( const unsigned if (dirty & DesktopViewport) { for (int i = 0; i < p->viewport.size(); i++) p->viewport[i].x = p->viewport[i].y = 0; - if (XGetWindowProperty(p->display, p->root, net_desktop_viewport, + if (KXReceiveWindowProperty(p->display, p->root, net_desktop_viewport, 0l, 2l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2362,7 +2425,7 @@ void NETRootInfo::update( const unsigned if (dirty & CurrentDesktop) { p->current_desktop = 0; - if (XGetWindowProperty(p->display, p->root, net_current_desktop, + if (KXReceiveWindowProperty(p->display, p->root, net_current_desktop, 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2383,7 +2446,7 @@ void NETRootInfo::update( const unsigned for( int i = 0; i < p->desktop_names.size(); ++i ) delete[] p->desktop_names[ i ]; p->desktop_names.reset(); - if (XGetWindowProperty(p->display, p->root, net_desktop_names, + if (KXReceiveWindowProperty(p->display, p->root, net_desktop_names, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2411,7 +2474,7 @@ void NETRootInfo::update( const unsigned if (dirty & ActiveWindow) { p->active = None; - if (XGetWindowProperty(p->display, p->root, net_active_window, 0l, 1l, + if (KXReceiveWindowProperty(p->display, p->root, net_active_window, 0l, 1l, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2430,8 +2493,8 @@ void NETRootInfo::update( const unsigned if (dirty & WorkArea) { p->workarea.reset(); - if (XGetWindowProperty(p->display, p->root, net_workarea, 0l, - (p->number_of_desktops * 4), False, XA_CARDINAL, + if (KXReceiveWindowProperty(p->display, p->root, net_workarea, 0l, + MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2461,7 +2524,8 @@ void NETRootInfo::update( const unsigned p->supportwindow = None; delete[] p->name; p->name = NULL; - if (XGetWindowProperty(p->display, p->root, net_supporting_wm_check, + bool was_2nd_read = false; + if (KXReceiveWindowProperty(p->display, p->root, net_supporting_wm_check, 0l, 1l, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2469,7 +2533,8 @@ void NETRootInfo::update( const unsigned p->supportwindow = *((Window *) data_ret); unsigned char *name_ret; - if (XGetWindowProperty(p->display, p->supportwindow, + was_2nd_read = true; + if (KXReceiveWindowProperty(p->display, p->supportwindow, net_wm_name, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &name_ret) @@ -2490,13 +2555,22 @@ void NETRootInfo::update( const unsigned if ( data_ret ) XFree(data_ret); } + if( !was_2nd_read ) { // read the second property if not needed, just in order to free the reply + unsigned char *name_ret; + if( KXReceiveWindowProperty(p->display, p->supportwindow, + net_wm_name, 0l, MAX_PROP_SIZE, False, + UTF8_STRING, &type_ret, &format_ret, + &nitems_ret, &unused, &name_ret) == Success + && name_ret ) + XFree( name_ret ); + } } if (dirty & VirtualRoots) { p->virtual_roots_count = 0; delete[] p->virtual_roots; p->virtual_roots = NULL; - if (XGetWindowProperty(p->display, p->root, net_virtual_roots, + if (KXReceiveWindowProperty(p->display, p->root, net_virtual_roots, 0, MAX_PROP_SIZE, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -2518,7 +2592,7 @@ void NETRootInfo::update( const unsigned if (dirty2 & WM2ShowingDesktop) { p->showing_desktop = false; - if (XGetWindowProperty(p->display, p->root, net_showing_desktop, + if (KXReceiveWindowProperty(p->display, p->root, net_showing_desktop, 0, MAX_PROP_SIZE, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3748,9 +3822,88 @@ void NETWinInfo::update(const unsigned l if( dirty_props[ PROTOCOLS ] & XAWMState ) props[ PROTOCOLS ] |= XAWMState; +// Property prefetching part. Duplicate calls to KXReceiveWindowProperty() +// as KXAskWindowProperty() calls here, without the out arguments. + if (dirty & XAWMState) + KXAskWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l, + False, xa_wm_state); + if (dirty & WMState) + KXAskWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l, + False, XA_ATOM); + if (dirty & WMDesktop) + KXAskWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l, + False, XA_CARDINAL); + if (dirty & WMName) + KXAskWindowProperty(p->display, p->window, net_wm_name, 0l, + MAX_PROP_SIZE, False, UTF8_STRING); + if (dirty & WMVisibleName) + KXAskWindowProperty(p->display, p->window, net_wm_visible_name, 0l, + MAX_PROP_SIZE, False, UTF8_STRING); + if (dirty & WMIconName) + KXAskWindowProperty(p->display, p->window, net_wm_icon_name, 0l, + MAX_PROP_SIZE, False, UTF8_STRING); + if (dirty & WMVisibleIconName) + KXAskWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l, + MAX_PROP_SIZE, False, UTF8_STRING); + if (dirty & WMWindowType) + KXAskWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l, + False, XA_ATOM); + if (dirty & WMStrut) + KXAskWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l, + False, XA_CARDINAL); + if (dirty2 & WM2ExtendedStrut) + KXAskWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l, + False, XA_CARDINAL); + if (dirty & WMIconGeometry) + KXAskWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l, + False, XA_CARDINAL); + if (dirty & WMIcon) + KXAskWindowProperty(p->display, p->window, net_wm_icon, 0l, + MAX_PROP_SIZE, False, XA_CARDINAL); + if (dirty & WMKDESystemTrayWinFor) + KXAskWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for, + 0l, 1l, False, XA_WINDOW); + if (dirty & WMFrameExtents) { + KXAskWindowProperty(p->display, p->window, net_frame_extents, + 0l, 4l, False, XA_CARDINAL); + KXAskWindowProperty(p->display, p->window, kde_net_wm_frame_strut, + 0l, 4l, False, XA_CARDINAL); + } + if (dirty & WMPid) + KXAskWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l, + False, XA_CARDINAL); + if (dirty2 & WM2StartupId) + KXAskWindowProperty(p->display, p->window, net_startup_id, 0l, + MAX_PROP_SIZE, False, UTF8_STRING); + if( dirty2 & WM2AllowedActions ) + KXAskWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l, + False, XA_ATOM); + if (dirty2 & WM2UserTime) + KXAskWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l, + False, XA_CARDINAL); +#if 0 + if (dirty2 & WM2TransientFor) +todo + XGetTransientForHint(p->display, p->window, &p->transient_for); + if (dirty2 & WM2GroupLeader) +todo + XWMHints *hints = XGetWMHints(p->display, p->window); + if( dirty2 & WM2WindowClass ) +todo + if( XGetClassHint( p->display, p->window, &hint )) +#endif + if( dirty2 & WM2WindowRole ) + KXAskWindowProperty(p->display, p->window, wm_window_role, 0l, + MAX_PROP_SIZE, False, XA_STRING); + if( dirty2 & WM2ClientMachine ) + KXAskWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l, + MAX_PROP_SIZE, False, XA_STRING); + +// The fetching part - when you update KXReceiveWindowProperty() calls here, +// update also the XAskWindowProperty() calls. if (dirty & XAWMState) { p->mapping_state = Withdrawn; - if (XGetWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l, + if (KXReceiveWindowProperty(p->display, p->window, xa_wm_state, 0l, 1l, False, xa_wm_state, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3780,7 +3933,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMState) { p->state = 0; - if (XGetWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_state, 0l, 2048l, False, XA_ATOM, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3839,7 +3992,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMDesktop) { p->desktop = 0; - if (XGetWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_desktop, 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) @@ -3861,7 +4014,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMName) { delete[] p->name; p->name = NULL; - if (XGetWindowProperty(p->display, p->window, net_wm_name, 0l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_name, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3877,7 +4030,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMVisibleName) { delete[] p->visible_name; p->visible_name = NULL; - if (XGetWindowProperty(p->display, p->window, net_wm_visible_name, 0l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_visible_name, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3893,7 +4046,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMIconName) { delete[] p->icon_name; p->icon_name = NULL; - if (XGetWindowProperty(p->display, p->window, net_wm_icon_name, 0l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_icon_name, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3910,7 +4063,7 @@ void NETWinInfo::update(const unsigned l { delete[] p->visible_icon_name; p->visible_icon_name = NULL; - if (XGetWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_visible_icon_name, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3927,7 +4080,7 @@ void NETWinInfo::update(const unsigned l p->types.reset(); p->types[ 0 ] = Unknown; p->has_net_support = false; - if (XGetWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_window_type, 0l, 2048l, False, XA_ATOM, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -3987,7 +4140,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMStrut) { p->strut = NETStrut(); - if (XGetWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_strut, 0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4006,7 +4159,7 @@ void NETWinInfo::update(const unsigned l if (dirty2 & WM2ExtendedStrut) { p->extended_strut = NETExtendedStrut(); - if (XGetWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_extended_strut, 0l, 12l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4033,7 +4186,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMIconGeometry) { p->icon_geom = NETRect(); - if (XGetWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_icon_geometry, 0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4051,12 +4204,12 @@ void NETWinInfo::update(const unsigned l } if (dirty & WMIcon) { - readIcon(p->display,p->window,net_wm_icon,p->icons,p->icon_count); + readIcon(p->display,p->window,net_wm_icon,p->icons,p->icon_count, true); } if (dirty & WMKDESystemTrayWinFor) { p->kde_system_tray_win_for = 0; - if (XGetWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for, + if (KXReceiveWindowProperty(p->display, p->window, kde_net_wm_system_tray_window_for, 0l, 1l, False, XA_WINDOW, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4074,7 +4227,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMFrameExtents) { p->frame_strut = NETStrut(); bool ok = false; - if (XGetWindowProperty(p->display, p->window, net_frame_extents, + if (KXReceiveWindowProperty(p->display, p->window, net_frame_extents, 0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) { @@ -4089,10 +4242,12 @@ void NETWinInfo::update(const unsigned l if ( data_ret ) XFree(data_ret); } - if (!ok && XGetWindowProperty(p->display, p->window, kde_net_wm_frame_strut, + // the !ok check is intentionally done only later, so that KXReceiveWindowProperty() + // always reads the received reply + if (KXReceiveWindowProperty(p->display, p->window, kde_net_wm_frame_strut, 0l, 4l, False, XA_CARDINAL, &type_ret, &format_ret, - &nitems_ret, &unused, &data_ret) == Success) { - if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) { + &nitems_ret, &unused, &data_ret) == Success ) { + if (!ok && type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 4) { ok = true; long *d = (long *) data_ret; @@ -4108,7 +4263,7 @@ void NETWinInfo::update(const unsigned l if (dirty & WMPid) { p->pid = 0; - if (XGetWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_pid, 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { if (type_ret == XA_CARDINAL && format_ret == 32 && nitems_ret == 1) { @@ -4123,7 +4278,7 @@ void NETWinInfo::update(const unsigned l { delete[] p->startup_id; p->startup_id = NULL; - if (XGetWindowProperty(p->display, p->window, net_startup_id, 0l, + if (KXReceiveWindowProperty(p->display, p->window, net_startup_id, 0l, MAX_PROP_SIZE, False, UTF8_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4138,7 +4293,7 @@ void NETWinInfo::update(const unsigned l if( dirty2 & WM2AllowedActions ) { p->allowed_actions = 0; - if (XGetWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_allowed_actions, 0l, 2048l, False, XA_ATOM, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4189,7 +4344,7 @@ void NETWinInfo::update(const unsigned l if (dirty2 & WM2UserTime) { p->user_time = -1U; - if (XGetWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l, + if (KXReceiveWindowProperty(p->display, p->window, net_wm_user_time, 0l, 1l, False, XA_CARDINAL, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { // don't do nitems_ret check - Qt does PropModeAppend to avoid API call for it @@ -4234,7 +4389,7 @@ void NETWinInfo::update(const unsigned l if( dirty2 & WM2WindowRole ) { delete[] p->role; p->role = NULL; - if (XGetWindowProperty(p->display, p->window, wm_window_role, 0l, + if (KXReceiveWindowProperty(p->display, p->window, wm_window_role, 0l, MAX_PROP_SIZE, False, XA_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { @@ -4249,7 +4404,7 @@ void NETWinInfo::update(const unsigned l if( dirty2 & WM2ClientMachine ) { delete[] p->client_machine; p->client_machine = NULL; - if (XGetWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l, + if (KXReceiveWindowProperty(p->display, p->window, XA_WM_CLIENT_MACHINE, 0l, MAX_PROP_SIZE, False, XA_STRING, &type_ret, &format_ret, &nitems_ret, &unused, &data_ret) == Success) { --- kdecore/kapplication.cpp.sav 2006-07-12 18:46:20.000000000 +0200 +++ kdecore/kapplication.cpp 2006-08-16 14:23:51.000000000 +0200 @@ -77,6 +77,7 @@ #if defined Q_WS_X11 #include +#include #endif #include @@ -1663,6 +1664,11 @@ KApplication::~KApplication() #else // FIXME(E): Implement for Qt Embedded #endif + +#ifdef Q_WS_X11 + if (Tty != kapp->type()) + KXPropertyCleanup( qt_xdisplay()); +#endif } --- kdecore/configure.in.in.sav 2005-11-30 16:54:00.000000000 +0100 +++ kdecore/configure.in.in 2006-08-16 12:28:39.000000000 +0200 @@ -231,3 +231,5 @@ AC_TRY_LINK(dnl ], AC_MSG_RESULT(no) ) + +KDE_CHECK_HEADER(X11/Xlib.h, [AC_DEFINE(HAVE_X11_XLIB_H,1,[Define to 1 if you have the header file.])]) --- kdecore/kasyncprop.c.sav 2006-08-16 11:47:21.000000000 +0200 +++ kdecore/kasyncprop.c 2006-08-16 15:49:59.000000000 +0200 @@ -0,0 +1,408 @@ +/* + * Copyright (C) 1986, 1998 The Open Group + * Copyright (C) 2002 Havoc Pennington + * Copyright (C) 2006 Lubos Lunak + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without + * fee, provided that the above copyright notice appear in all copies + * and that both that copyright notice and this permission notice + * appear in supporting documentation. + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of The Open Group shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from The Open Group. + */ + +#include "kasyncprop.h" + +#include "kdelibs_export.h" + +#include +#ifdef HAVE_X11_XLIB_H + +/* This code is a replacement for XGetWindowProperty() that allows batching + of the requests - normally every single XGetWindowProperty() means one + Xserver roundtrip. For several XGetWindowProperty() calls it's better + to replace them by a series of XAskWindowProperty() calls that will + request the properties and then a series of matching XReceiveWindowProperty() + calls to actually retrieve the properties. Such a batch of requests + causes only one Xserver roundtrip. +*/ + + +/*#define NEED_REPLIES*/ +#include + +#include + +typedef struct _XPropertyData { + struct _XPropertyData* next; + Window window; + Atom property; + Bool delete; + Atom req_type; + Atom actual_type; + int actual_format; + long offset; + long length; + unsigned long nitems; + unsigned long bytesafter; + char* prop; + int status; + unsigned long sequence; +} _XPropertyData; + +static _XPropertyData* data_pending; +static _XPropertyData** data_pending_last; +static _XPropertyData* data_done; +static _XPropertyData** data_done_last; +static _XAsyncHandler async; +static unsigned long last_reply; + +#define LIST_REMOVE_ITEM( item, pos, last ) \ + *pos = item->next; \ + if( last == &item->next ) \ + last = pos; + +#define LIST_APPEND_ITEM( item, last ) \ + *last = item; \ + item->next = NULL; \ + last = &(item->next); + +static _XPropertyData* _XPropertyRemovePending( unsigned long sequenceNumber ) +{ +#if 1 +/* Replies come in the same order like requests were sent, so just pick the first one. */ + if( data_pending == NULL ) + return NULL; + if( data_pending->sequence == sequenceNumber ) + { + _XPropertyData* item = data_pending; + _XPropertyData** pos = &data_pending; + LIST_REMOVE_ITEM( item, pos, data_pending_last ) + LIST_APPEND_ITEM( item, data_done_last ) + return item; + } + return NULL; +#else + _XPropertyData** pos = &data_pending; + while( *pos != NULL ) + { + if( (*pos)->sequence == sequenceNumber ) + { + _XPropertyData* item = *pos; + LIST_REMOVE_ITEM( item, pos, data_pending_last ) + LIST_APPEND_ITEM( item, data_done_last ) + return item; + } + pos = &((*pos)->next); + } + return NULL; +#endif +} + +static Bool _XPropertyHandler( Display* dpy, xReply* rep, char* buf, int len, XPointer data ) +{ + xGetPropertyReply replbuf; + register xGetPropertyReply *repl; + _XPropertyData* item; + + (void)data; + (void)dpy; + + /* rep->generic.sequenceNumber contains only lowest 16bits of the sequence, + use dpy->last_request_read */ + item = _XPropertyRemovePending( dpy->last_request_read ); + if( item == NULL ) /* not a reply to our request */ + return False; + +/* + TODO: remove old replies that haven't been read using XReceiveWindowProperty() + for some reason? Sequence numbers wrap around and there's a tiny chance old + values could be reused. Additionally keeping old values wastes memory (although + failing to use matching XReceiveWindowProperty() is considered to be an error). +*/ + if (rep->generic.type == X_Error) { +/* Metacity here discards the error, arguing that async API should not require + synchronous trapping of errors, but I disagree. This API is meant for + reading data in bursts, so it kind of is synchronous anyway. */ + item->status = rep->error.errorCode; + return False; + } + repl = (xGetPropertyReply *) + _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len, + (SIZEOF(xGetPropertyReply) - SIZEOF(xReply)) >> 2, + False); + item->prop = NULL; + if (repl->propertyType != None) { + long nbytes, netbytes; + switch (repl->format) { + /* + * One extra byte is malloced than is needed to contain the property + * data, but this last byte is null terminated and convenient for + * returning string properties, so the client doesn't then have to + * recopy the string to make it null terminated. + */ + case 8: + nbytes = netbytes = repl->nItems; + netbytes = ( netbytes + 3 ) & ~3; /* align to 4 */ + if (nbytes + 1 > 0 && + (item->prop = Xmalloc ((unsigned)nbytes + 1))) { + _XGetAsyncData(dpy, item->prop, buf, len, + SIZEOF(xGetPropertyReply), nbytes, + netbytes); + } + break; + + case 16: + nbytes = repl->nItems * sizeof (short); + netbytes = repl->nItems << 1; + netbytes = ( netbytes + 3 ) & ~3; /* align to 4 */ + if (nbytes + 1 > 0 && + (item->prop = Xmalloc ((unsigned)nbytes + 1))) { + _XGetAsyncData(dpy, item->prop, buf, len, + SIZEOF(xGetPropertyReply), nbytes, + netbytes); + } + break; + + case 32: + nbytes = repl->nItems * sizeof (long); + netbytes = repl->nItems << 2; + if (nbytes + 1 > 0 && + (item->prop = Xmalloc ((unsigned)nbytes + 1))) { + if( sizeof( long ) == 4 ) { + _XGetAsyncData(dpy, item->prop, buf, len, + SIZEOF(xGetPropertyReply), nbytes, + netbytes); + } else { /* format 32 is long even on 64bit platforms */ + _XGetAsyncData(dpy, item->prop, buf, len, + SIZEOF(xGetPropertyReply), netbytes, + netbytes); + long* dst = (( long* ) item->prop ) + repl->nItems - 1; + CARD32* src = (( CARD32* ) item->prop ) + repl->nItems - 1; + int i; + for( i = repl->nItems; + i > 0; + --i ) + *dst-- = *src--; + } + } + break; + + default: + /* + * This part of the code should never be reached. If it is, + * the server sent back a property with an invalid format. + * This is a BadImplementation error. + */ + item->status = BadImplementation; + nbytes = netbytes = 0L; + break; + } + if (! item->prop) { + _XGetAsyncData(dpy, NULL, buf, len, + SIZEOF(xGetPropertyReply), 0, + netbytes); + + item->status = BadAlloc; /* not Success */ + return True; + } + (item->prop)[nbytes] = '\0'; + } + item->actual_type = repl->propertyType; + item->actual_format = repl->format; + item->nitems = repl->nItems; + item->bytesafter = repl->bytesAfter; + return True; +} + +static int init = 0; + +static void XPropertyInit( Display* dpy ) +{ + LockDisplay(dpy); + if( init ) + { + UnlockDisplay(dpy); + return; + } + init = 1; +/* fprintf(stderr,"Init: %ld\n", dpy->request ); */ + data_pending = NULL; + data_pending_last = &data_pending; + data_done = NULL; + data_done_last = &data_done; + last_reply = dpy->last_request_read; + async.next = dpy->async_handlers; + async.handler = _XPropertyHandler; + async.data = NULL; + dpy->async_handlers = &async; + UnlockDisplay(dpy); +} + +static int _XPropertyGetReply( Window w, Atom property, long offset, long length, Bool delete, + Atom req_type, Atom* actual_type, int* actual_format, unsigned long* nitems, + unsigned long* bytesafter, unsigned char** prop, int* status ) +{ + _XPropertyData** pos; + for( pos = &data_done; + *pos != NULL; + pos = &((*pos)->next)) + { + _XPropertyData* item = *pos; + if( item->window != w ) + continue; + if( item->property != property ) + continue; + if( item->delete != delete + || item->req_type != req_type + || item->offset != offset + || item->length != length ) + continue; + /* found */ + *actual_type = item->actual_type; + *actual_format = item->actual_format; + *nitems = item->nitems; + *bytesafter = item->bytesafter; + *prop = ( unsigned char* )item->prop; + *status = item->status; + LIST_REMOVE_ITEM( item, pos, data_done_last ) + XFree( item ); + return True; + } + return False; +} + + +KDECORE_EXPORT void KXAskWindowProperty( Display* dpy, Window w, Atom property, long offset, + long length, Bool delete, Atom req_type ) +{ + register xGetPropertyReq *req; + _XPropertyData* item; + + XPropertyInit( dpy ); + + LockDisplay(dpy); + + GetReq (GetProperty, req); + req->window = w; + req->property = property; + req->type = req_type; + req->delete = delete; + req->longOffset = offset; + req->longLength = length; + item = Xmalloc( sizeof( _XPropertyData )); + item->window = w; + item->property = property; + item->delete = delete; + item->req_type = req_type; + item->actual_type = None; + item->actual_format = 0; + item->offset = offset; + item->length = length; + item->nitems = 0; + item->bytesafter = 0; + item->prop = NULL; + item->status = Success; + item->sequence = dpy->request; + LIST_APPEND_ITEM( item, data_pending_last ) +/* fprintf( stderr, "Ask: 0x%ld 0x%ld %ld\n", w, property, dpy->request );*/ + UnlockDisplay(dpy); + SyncHandle(); +} + +KDECORE_EXPORT int KXReceiveWindowProperty( Display* dpy, Window w, Atom property, long offset, + long length, Bool delete, Atom req_type, Atom* actual_type, int* actual_format, + unsigned long* nitems, unsigned long* bytesafter, unsigned char** prop ) +{ + int ret; + + XPropertyInit( dpy ); + +/* fprintf( stderr, "Receive: 0x%ld 0x%ld\n", w, property ); */ + + LockDisplay(dpy); + + if( _XPropertyGetReply( w, property, offset, length, delete, req_type, + actual_type, actual_format, nitems, bytesafter, prop, &ret )) + { +/* fprintf( stderr, "Receive1\n" ); */ + UnlockDisplay(dpy); + return ret; + } + + /* + * XSync (dpy, 0) + */ + { + xGetInputFocusReply rep; + register xReq *req; + + GetEmptyReq(GetInputFocus, req); + (void) _XReply (dpy, (xReply *)&rep, 0, xTrue); + } + + /* check again, after sync */ + if( _XPropertyGetReply( w, property, offset, length, delete, req_type, + actual_type, actual_format, nitems, bytesafter, prop, &ret )) + { +/* fprintf( stderr, "Receive2\n" ); */ + UnlockDisplay(dpy); + SyncHandle(); + return ret; + } +/* fprintf( stderr, "Receive3\n" ); */ + UnlockDisplay(dpy); + SyncHandle(); + return BadValue; /* this should not(?) happen */ +} + +KDECORE_EXPORT void KXPropertyCleanup( Display* dpy ) +{ + _XPropertyData* pos; + _XPropertyData* pos2; + XSync( dpy, False ); + LockDisplay(dpy); + if( init ) + { + int pending = 0; + int done = 0; + DeqAsyncHandler(dpy, &async); + pos = data_pending; + while( pos != NULL ) + { + pos2 = pos->next; + XFree( pos ); + pos = pos2; + ++pending; + } + pos = data_done; + while( pos != NULL ) + { + pos2 = pos->next; + XFree( pos ); + pos = pos2; + ++done; + } +#ifndef NDEBUG + if( pending > 0 || done > 0 ) + fprintf(stderr,"XAskWindowProperty cleanup: %d pending requests, %d pending replies\n", pending, done ); +#endif + init = 0; + } + UnlockDisplay(dpy); +} +#endif --Boundary-00=_zkw7EB9ZV3KrcMT Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Kde-optimize mailing list Kde-optimize@kde.org https://mail.kde.org/mailman/listinfo/kde-optimize --Boundary-00=_zkw7EB9ZV3KrcMT--