utils.cpp

00001 /*****************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00007 
00008 You can Freely distribute this program under the GNU General Public
00009 License. See the file "COPYING" for the exact licensing terms.
00010 ******************************************************************/
00011 
00012 /*
00013 
00014  This file is for (very) small utility functions/classes.
00015 
00016 */
00017 
00018 #include "utils.h"
00019 
00020 #include <unistd.h>
00021 
00022 #ifndef KCMRULES
00023 
00024 #include <kxerrorhandler.h>
00025 #include <assert.h>
00026 #include <kdebug.h>
00027 
00028 #include <X11/Xlib.h>
00029 #include <X11/extensions/shape.h>
00030 #include <X11/Xatom.h>
00031 
00032 #include "atoms.h"
00033 #include "notifications.h"
00034 
00035 extern Time qt_x_time;
00036 
00037 #endif
00038 
00039 namespace KWinInternal
00040 {
00041 
00042 #ifndef KCMRULES
00043 
00044 // used to store the return values of
00045 // XShapeQueryExtension.
00046 // Necessary since shaped window are an extension to X
00047 int Shape::kwin_has_shape = 0;
00048 int Shape::kwin_shape_event = 0;
00049 
00050 // does the window w  need a shape combine mask around it?
00051 bool Shape::hasShape( WId w)
00052     {
00053     int xws, yws, xbs, ybs;
00054     unsigned int wws, hws, wbs, hbs;
00055     int boundingShaped = 0, clipShaped = 0;
00056     if (!kwin_has_shape)
00057         return FALSE;
00058     XShapeQueryExtents(qt_xdisplay(), w,
00059                        &boundingShaped, &xws, &yws, &wws, &hws,
00060                        &clipShaped, &xbs, &ybs, &wbs, &hbs);
00061     return boundingShaped != 0;
00062     }
00063 
00064 int Shape::shapeEvent()
00065     {
00066     return kwin_shape_event;
00067     }
00068 
00069 void Shape::init()
00070     {
00071     int dummy;
00072     kwin_has_shape =
00073       XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy);
00074     }
00075 
00076 void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move,
00077     bool& minimize, bool& maximize, bool& close )
00078     {
00079     Atom type;
00080     int format;
00081     unsigned long length, after;
00082     unsigned char* data;
00083     MwmHints* hints = 0;
00084     if ( XGetWindowProperty( qt_xdisplay(), w, atoms->motif_wm_hints, 0, 5,
00085                              FALSE, atoms->motif_wm_hints, &type, &format,
00086                              &length, &after, &data ) == Success ) 
00087         {
00088         if ( data )
00089             hints = (MwmHints*) data;
00090         }
00091     noborder = false;
00092     resize = true;
00093     move = true;
00094     minimize = true;
00095     maximize = true;
00096     close = true;
00097     if ( hints ) 
00098         {
00099     // To quote from Metacity 'We support those MWM hints deemed non-stupid'
00100         if ( hints->flags & MWM_HINTS_FUNCTIONS ) 
00101             {
00102             // if MWM_FUNC_ALL is set, other flags say what to turn _off_
00103             bool set_value = (( hints->functions & MWM_FUNC_ALL ) == 0 );
00104             resize = move = minimize = maximize = close = !set_value;
00105             if( hints->functions & MWM_FUNC_RESIZE )
00106                 resize = set_value;
00107             if( hints->functions & MWM_FUNC_MOVE )
00108                 move = set_value;
00109             if( hints->functions & MWM_FUNC_MINIMIZE )
00110                 minimize = set_value;
00111             if( hints->functions & MWM_FUNC_MAXIMIZE )
00112                 maximize = set_value;
00113             if( hints->functions & MWM_FUNC_CLOSE )
00114                 close = set_value;
00115             }
00116         if ( hints->flags & MWM_HINTS_DECORATIONS ) 
00117             {
00118             if ( hints->decorations == 0 )
00119                 noborder = true;
00120             }
00121         XFree( data );
00122         }
00123     }
00124 
00125 //************************************
00126 // KWinSelectionOwner
00127 //************************************
00128 
00129 KWinSelectionOwner::KWinSelectionOwner( int screen_P )
00130     : KSelectionOwner( make_selection_atom( screen_P ), screen_P )
00131     {
00132     }
00133 
00134 Atom KWinSelectionOwner::make_selection_atom( int screen_P )
00135     {
00136     if( screen_P < 0 )
00137         screen_P = DefaultScreen( qt_xdisplay());
00138     char tmp[ 30 ];
00139     sprintf( tmp, "WM_S%d", screen_P );
00140     return XInternAtom( qt_xdisplay(), tmp, False );
00141     }
00142 
00143 void KWinSelectionOwner::getAtoms()
00144     {
00145     KSelectionOwner::getAtoms();
00146     if( xa_version == None )
00147         {
00148         Atom atoms[ 1 ];
00149         const char* const names[] =
00150             { "VERSION" };
00151         XInternAtoms( qt_xdisplay(), const_cast< char** >( names ), 1, False, atoms );
00152         xa_version = atoms[ 0 ];
00153         }
00154     }
00155 
00156 void KWinSelectionOwner::replyTargets( Atom property_P, Window requestor_P )
00157     {
00158     KSelectionOwner::replyTargets( property_P, requestor_P );
00159     Atom atoms[ 1 ] = { xa_version };
00160     // PropModeAppend !
00161     XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_ATOM, 32, PropModeAppend,
00162         reinterpret_cast< unsigned char* >( atoms ), 1 );
00163     }
00164 
00165 bool KWinSelectionOwner::genericReply( Atom target_P, Atom property_P, Window requestor_P )
00166     {
00167     if( target_P == xa_version )
00168         {
00169         long version[] = { 2, 0 };
00170         XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_INTEGER, 32,
00171             PropModeReplace, reinterpret_cast< unsigned char* >( &version ), 2 );
00172         }
00173     else
00174         return KSelectionOwner::genericReply( target_P, property_P, requestor_P );
00175     return true;    
00176     }
00177 
00178 Atom KWinSelectionOwner::xa_version = None;
00179 
00180 
00181 QCString getStringProperty(WId w, Atom prop, char separator)
00182     {
00183     Atom type;
00184     int format, status;
00185     unsigned long nitems = 0;
00186     unsigned long extra = 0;
00187     unsigned char *data = 0;
00188     QCString result = "";
00189     KXErrorHandler handler; // ignore errors
00190     status = XGetWindowProperty( qt_xdisplay(), w, prop, 0, 10000,
00191                                  FALSE, XA_STRING, &type, &format,
00192                                  &nitems, &extra, &data );
00193     if ( status == Success) 
00194         {
00195         if (data && separator) 
00196             {
00197             for (int i=0; i<(int)nitems; i++)
00198                 if (!data[i] && i+1<(int)nitems)
00199                     data[i] = separator;
00200             }
00201         if (data)
00202             result = (const char*) data;
00203         XFree(data);
00204         }
00205     return result;
00206     }
00207 
00208 static Time next_x_time;
00209 static Bool update_x_time_predicate( Display*, XEvent* event, XPointer )
00210 {
00211     if( next_x_time != CurrentTime )
00212         return False;
00213     // from qapplication_x11.cpp
00214     switch ( event->type ) {
00215     case ButtonPress:
00216     // fallthrough intended
00217     case ButtonRelease:
00218     next_x_time = event->xbutton.time;
00219     break;
00220     case MotionNotify:
00221     next_x_time = event->xmotion.time;
00222     break;
00223     case KeyPress:
00224     // fallthrough intended
00225     case KeyRelease:
00226     next_x_time = event->xkey.time;
00227     break;
00228     case PropertyNotify:
00229     next_x_time = event->xproperty.time;
00230     break;
00231     case EnterNotify:
00232     case LeaveNotify:
00233     next_x_time = event->xcrossing.time;
00234     break;
00235     case SelectionClear:
00236     next_x_time = event->xselectionclear.time;
00237     break;
00238     default:
00239     break;
00240     }
00241     return False;
00242 }
00243 
00244 /*
00245  Updates qt_x_time. This used to simply fetch current timestamp from the server,
00246  but that can cause qt_x_time to be newer than timestamp of events that are
00247  still in our events queue, thus e.g. making XSetInputFocus() caused by such
00248  event to be ignored. Therefore events queue is searched for first
00249  event with timestamp, and extra PropertyNotify is generated in order to make
00250  sure such event is found.
00251 */
00252 void updateXTime()
00253     {
00254     static QWidget* w = 0;
00255     if ( !w )
00256         w = new QWidget;
00257     long data = 1;
00258     XChangeProperty(qt_xdisplay(), w->winId(), atoms->kwin_running, atoms->kwin_running, 32,
00259                     PropModeAppend, (unsigned char*) &data, 1);
00260     next_x_time = CurrentTime;
00261     XEvent dummy;
00262     XCheckIfEvent( qt_xdisplay(), &dummy, update_x_time_predicate, NULL );
00263     if( next_x_time == CurrentTime )
00264         {
00265         XSync( qt_xdisplay(), False );
00266         XCheckIfEvent( qt_xdisplay(), &dummy, update_x_time_predicate, NULL );
00267         }
00268     assert( next_x_time != CurrentTime );
00269     qt_x_time = next_x_time;
00270     XEvent ev; // remove the PropertyNotify event from the events queue
00271     XWindowEvent( qt_xdisplay(), w->winId(), PropertyChangeMask, &ev );
00272     }
00273 
00274 static int server_grab_count = 0;
00275 
00276 void grabXServer()
00277     {
00278     if( ++server_grab_count == 1 )
00279         XGrabServer( qt_xdisplay());
00280     }
00281 
00282 void ungrabXServer()
00283     {
00284     assert( server_grab_count > 0 );
00285     if( --server_grab_count == 0 )
00286         {
00287         XUngrabServer( qt_xdisplay());
00288         XFlush( qt_xdisplay());
00289         Notify::sendPendingEvents();
00290         }
00291     }
00292     
00293 bool grabbedXServer()
00294     {
00295     return server_grab_count > 0;
00296     }
00297 
00298 #endif
00299 
00300 bool isLocalMachine( const QCString& host )
00301     {
00302 #ifdef HOST_NAME_MAX
00303     char hostnamebuf[HOST_NAME_MAX];
00304 #else
00305     char hostnamebuf[256];
00306 #endif
00307     if (gethostname (hostnamebuf, sizeof hostnamebuf) >= 0) 
00308         {
00309         hostnamebuf[sizeof(hostnamebuf)-1] = 0;
00310         if (host == hostnamebuf)
00311             return true;
00312         char *dot = strchr(hostnamebuf, '.');
00313         if (dot && !(*dot = 0) && host == hostnamebuf)
00314             return true;
00315         }
00316     return false;
00317     }
00318 
00319 #ifndef KCMRULES
00320 ShortcutDialog::ShortcutDialog( const KShortcut& cut )
00321     : KShortcutDialog( cut, false /*TODO???*/ )
00322     {
00323     // make it a popup, so that it has the grab
00324     XSetWindowAttributes attrs;
00325     attrs.override_redirect = True;
00326     XChangeWindowAttributes( qt_xdisplay(), winId(), CWOverrideRedirect, &attrs );
00327     setWFlags( WType_Popup );
00328     }
00329 
00330 void ShortcutDialog::accept()
00331     {
00332     for( int i = 0;
00333          ;
00334          ++i )
00335         {
00336         KKeySequence seq = shortcut().seq( i );
00337         if( seq.isNull())
00338             break;
00339         if( seq.key( 0 ) == Key_Escape )
00340             {
00341             reject();
00342             return;
00343             }
00344         if( seq.key( 0 ) == Key_Space )
00345             { // clear
00346             setShortcut( KShortcut());
00347             KShortcutDialog::accept();
00348             return;
00349             }
00350         if( seq.key( 0 ).modFlags() == 0 )
00351             { // no shortcuts without modifiers
00352             KShortcut cut = shortcut();
00353             cut.setSeq( i, KKeySequence());
00354             setShortcut( cut );
00355             return;
00356             }
00357         }
00358     KShortcutDialog::accept();
00359     }
00360 #endif
00361 
00362 
00363 } // namespace
00364 
00365 #ifndef KCMRULES
00366 #include "utils.moc"
00367 #endif
KDE Home | KDE Accessibility Home | Description of Access Keys