• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kwin
 

kwin

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 #include <string.h>
00022 #include <netdb.h>
00023 
00024 #ifndef KCMRULES
00025 
00026 #include <tqapplication.h>
00027 #include <kxerrorhandler.h>
00028 #include <assert.h>
00029 #include <kdebug.h>
00030 
00031 #include <X11/Xlib.h>
00032 #include <X11/extensions/shape.h>
00033 #include <X11/Xatom.h>
00034 
00035 #include "atoms.h"
00036 #include "notifications.h"
00037 
00038 #ifdef USE_QT4
00039 #include <Qt/qx11info_x11.h>
00040 #endif // USE_QT4
00041 
00042 #endif
00043 
00044 namespace KWinInternal
00045 {
00046 
00047 #ifndef KCMRULES
00048 
00049 // used to store the return values of
00050 // XShapeQueryExtension.
00051 // Necessary since shaped window are an extension to X
00052 int Shape::kwin_shape_version = 0;
00053 int Shape::kwin_shape_event = 0;
00054 
00055 // does the window w  need a shape combine mask around it?
00056 bool Shape::hasShape( WId w)
00057     {
00058     int xws, yws, xbs, ybs;
00059     unsigned int wws, hws, wbs, hbs;
00060     int boundingShaped = 0, clipShaped = 0;
00061     if (!available())
00062         return FALSE;
00063     XShapeQueryExtents(qt_xdisplay(), w,
00064                        &boundingShaped, &xws, &yws, &wws, &hws,
00065                        &clipShaped, &xbs, &ybs, &wbs, &hbs);
00066     return boundingShaped != 0;
00067     }
00068 
00069 int Shape::shapeEvent()
00070     {
00071     return kwin_shape_event;
00072     }
00073 
00074 void Shape::init()
00075     {
00076     kwin_shape_version = 0;
00077     int dummy;
00078     if( !XShapeQueryExtension(qt_xdisplay(), &kwin_shape_event, &dummy))
00079         return;
00080     int major, minor;
00081     if( !XShapeQueryVersion( qt_xdisplay(), &major, &minor ))
00082         return;
00083     kwin_shape_version = major * 0x10 + minor;
00084     }
00085 
00086 void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move,
00087     bool& minimize, bool& maximize, bool& close )
00088     {
00089     Atom type;
00090     int format;
00091     unsigned long length, after;
00092     unsigned char* data;
00093     MwmHints* hints = 0;
00094     if ( XGetWindowProperty( qt_xdisplay(), w, atoms->motif_wm_hints, 0, 5,
00095                              FALSE, atoms->motif_wm_hints, &type, &format,
00096                              &length, &after, &data ) == Success ) 
00097         {
00098         if ( data )
00099             hints = (MwmHints*) data;
00100         }
00101     noborder = false;
00102     resize = true;
00103     move = true;
00104     minimize = true;
00105     maximize = true;
00106     close = true;
00107     if ( hints ) 
00108         {
00109     // To quote from Metacity 'We support those MWM hints deemed non-stupid'
00110         if ( hints->flags & MWM_HINTS_FUNCTIONS ) 
00111             {
00112             // if MWM_FUNC_ALL is set, other flags say what to turn _off_
00113             bool set_value = (( hints->functions & MWM_FUNC_ALL ) == 0 );
00114             resize = move = minimize = maximize = close = !set_value;
00115             if( hints->functions & MWM_FUNC_RESIZE )
00116                 resize = set_value;
00117             if( hints->functions & MWM_FUNC_MOVE )
00118                 move = set_value;
00119             if( hints->functions & MWM_FUNC_MINIMIZE )
00120                 minimize = set_value;
00121             if( hints->functions & MWM_FUNC_MAXIMIZE )
00122                 maximize = set_value;
00123             if( hints->functions & MWM_FUNC_CLOSE )
00124                 close = set_value;
00125             }
00126         if ( hints->flags & MWM_HINTS_DECORATIONS ) 
00127             {
00128             if ( hints->decorations == 0 )
00129                 noborder = true;
00130             }
00131         XFree( data );
00132         }
00133     }
00134 
00135 //************************************
00136 // KWinSelectionOwner
00137 //************************************
00138 
00139 KWinSelectionOwner::KWinSelectionOwner( int screen_P )
00140     : KSelectionOwner( make_selection_atom( screen_P ), screen_P )
00141     {
00142     }
00143 
00144 Atom KWinSelectionOwner::make_selection_atom( int screen_P )
00145     {
00146     if( screen_P < 0 )
00147         screen_P = DefaultScreen( qt_xdisplay());
00148     char tmp[ 30 ];
00149     sprintf( tmp, "WM_S%d", screen_P );
00150     return XInternAtom( qt_xdisplay(), tmp, False );
00151     }
00152 
00153 void KWinSelectionOwner::getAtoms()
00154     {
00155     KSelectionOwner::getAtoms();
00156     if( xa_version == None )
00157         {
00158         Atom atoms[ 1 ];
00159         const char* const names[] =
00160             { "VERSION" };
00161         XInternAtoms( qt_xdisplay(), const_cast< char** >( names ), 1, False, atoms );
00162         xa_version = atoms[ 0 ];
00163         }
00164     }
00165 
00166 void KWinSelectionOwner::replyTargets( Atom property_P, Window requestor_P )
00167     {
00168     KSelectionOwner::replyTargets( property_P, requestor_P );
00169     Atom atoms[ 1 ] = { xa_version };
00170     // PropModeAppend !
00171     XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_ATOM, 32, PropModeAppend,
00172         reinterpret_cast< unsigned char* >( atoms ), 1 );
00173     }
00174 
00175 bool KWinSelectionOwner::genericReply( Atom target_P, Atom property_P, Window requestor_P )
00176     {
00177     if( target_P == xa_version )
00178         {
00179         long version[] = { 2, 0 };
00180         XChangeProperty( qt_xdisplay(), requestor_P, property_P, XA_INTEGER, 32,
00181             PropModeReplace, reinterpret_cast< unsigned char* >( &version ), 2 );
00182         }
00183     else
00184         return KSelectionOwner::genericReply( target_P, property_P, requestor_P );
00185     return true;    
00186     }
00187 
00188 Atom KWinSelectionOwner::xa_version = None;
00189 
00190 
00191 TQCString getStringProperty(WId w, Atom prop, char separator)
00192     {
00193     Atom type;
00194     int format, status;
00195     unsigned long nitems = 0;
00196     unsigned long extra = 0;
00197     unsigned char *data = 0;
00198     TQCString result = "";
00199     KXErrorHandler handler; // ignore errors
00200     status = XGetWindowProperty( qt_xdisplay(), w, prop, 0, 10000,
00201                                  FALSE, XA_STRING, &type, &format,
00202                                  &nitems, &extra, &data );
00203     if ( status == Success) 
00204         {
00205         if (data && separator) 
00206             {
00207             for (int i=0; i<(int)nitems; i++)
00208                 if (!data[i] && i+1<(int)nitems)
00209                     data[i] = separator;
00210             }
00211         if (data)
00212             result = (const char*) data;
00213         XFree(data);
00214         }
00215     return result;
00216     }
00217 
00218 static Time next_x_time;
00219 static Bool update_x_time_predicate( Display*, XEvent* event, XPointer )
00220 {
00221     if( next_x_time != CurrentTime )
00222         return False;
00223     // from qapplication_x11.cpp
00224     switch ( event->type ) {
00225     case ButtonPress:
00226     // fallthrough intended
00227     case ButtonRelease:
00228     next_x_time = event->xbutton.time;
00229     break;
00230     case MotionNotify:
00231     next_x_time = event->xmotion.time;
00232     break;
00233     case KeyPress:
00234     // fallthrough intended
00235     case KeyRelease:
00236     next_x_time = event->xkey.time;
00237     break;
00238     case PropertyNotify:
00239     next_x_time = event->xproperty.time;
00240     break;
00241     case EnterNotify:
00242     case LeaveNotify:
00243     next_x_time = event->xcrossing.time;
00244     break;
00245     case SelectionClear:
00246     next_x_time = event->xselectionclear.time;
00247     break;
00248     default:
00249     break;
00250     }
00251     return False;
00252 }
00253 
00254 /*
00255  Updates qt_x_time. This used to simply fetch current timestamp from the server,
00256  but that can cause qt_x_time to be newer than timestamp of events that are
00257  still in our events queue, thus e.g. making XSetInputFocus() caused by such
00258  event to be ignored. Therefore events queue is searched for first
00259  event with timestamp, and extra PropertyNotify is generated in order to make
00260  sure such event is found.
00261 */
00262 void updateXTime()
00263     {
00264     static TQWidget* w = 0;
00265     if ( !w )
00266         w = new TQWidget;
00267     long data = 1;
00268     XChangeProperty(qt_xdisplay(), w->winId(), atoms->kwin_running, atoms->kwin_running, 32,
00269                     PropModeAppend, (unsigned char*) &data, 1);
00270     next_x_time = CurrentTime;
00271     XEvent dummy;
00272     XCheckIfEvent( qt_xdisplay(), &dummy, update_x_time_predicate, NULL );
00273     if( next_x_time == CurrentTime )
00274         {
00275         XSync( qt_xdisplay(), False );
00276         XCheckIfEvent( qt_xdisplay(), &dummy, update_x_time_predicate, NULL );
00277         }
00278     assert( next_x_time != CurrentTime );
00279     SET_QT_X_TIME(next_x_time);
00280     XEvent ev; // remove the PropertyNotify event from the events queue
00281     XWindowEvent( qt_xdisplay(), w->winId(), PropertyChangeMask, &ev );
00282     }
00283 
00284 static int server_grab_count = 0;
00285 
00286 void grabXServer()
00287     {
00288     if( ++server_grab_count == 1 )
00289         XGrabServer( qt_xdisplay());
00290     }
00291 
00292 void ungrabXServer()
00293     {
00294     assert( server_grab_count > 0 );
00295     if( --server_grab_count == 0 )
00296         {
00297         XUngrabServer( qt_xdisplay());
00298         XFlush( qt_xdisplay());
00299         Notify::sendPendingEvents();
00300         }
00301     }
00302     
00303 bool grabbedXServer()
00304     {
00305     return server_grab_count > 0;
00306     }
00307 
00308 #endif
00309 
00310 bool isLocalMachine( const TQCString& host )
00311     {
00312 #ifdef HOST_NAME_MAX
00313     char hostnamebuf[HOST_NAME_MAX];
00314 #else
00315     char hostnamebuf[256];
00316 #endif
00317     if (gethostname (hostnamebuf, sizeof hostnamebuf) >= 0) 
00318         {
00319         hostnamebuf[sizeof(hostnamebuf)-1] = 0;
00320         if (host == hostnamebuf)
00321             return true;
00322         if( char *dot = strchr(hostnamebuf, '.'))
00323             {
00324             *dot = '\0';
00325             if( host == hostnamebuf )
00326                 return true;
00327             }
00328         else
00329             { // e.g. LibreOffice likes to give FQDN, even if gethostname() doesn't include domain
00330             struct addrinfo hints, *res, *addr;
00331             bool is_local = false;
00332 
00333             memset (&hints, 0, sizeof (hints));
00334             hints.ai_family = PF_UNSPEC;
00335             hints.ai_socktype = SOCK_STREAM;
00336             hints.ai_flags |= AI_CANONNAME;
00337 
00338             if( getaddrinfo( host, NULL, &hints, &res ) != 0)
00339                 return false;
00340             for(addr = res; !is_local && addr; addr = addr->ai_next)
00341                 {
00342                 if( addr->ai_canonname &&
00343                     host == TQCString( addr->ai_canonname ))
00344                     is_local = true;
00345                 }
00346             freeaddrinfo(res);
00347             return is_local;
00348             }
00349         }
00350     return false;
00351     }
00352 
00353 #ifndef KCMRULES
00354 ShortcutDialog::ShortcutDialog( const KShortcut& cut )
00355     : KShortcutDialog( cut, false /*TODO???*/ )
00356     {
00357     // make it a popup, so that it has the grab
00358     XSetWindowAttributes attrs;
00359     attrs.override_redirect = True;
00360     XChangeWindowAttributes( qt_xdisplay(), winId(), CWOverrideRedirect, &attrs );
00361     setWFlags( WType_Popup );
00362     }
00363 
00364 void ShortcutDialog::accept()
00365     {
00366     for( int i = 0;
00367          ;
00368          ++i )
00369         {
00370         KKeySequence seq = shortcut().seq( i );
00371         if( seq.isNull())
00372             break;
00373         if( seq.key( 0 ) == Key_Escape )
00374             {
00375             reject();
00376             return;
00377             }
00378         if( seq.key( 0 ) == Key_Space )
00379             { // clear
00380             setShortcut( KShortcut());
00381             KShortcutDialog::accept();
00382             return;
00383             }
00384         if( seq.key( 0 ).modFlags() == 0 )
00385             { // no shortcuts without modifiers
00386             KShortcut cut = shortcut();
00387             cut.setSeq( i, KKeySequence());
00388             setShortcut( cut );
00389             return;
00390             }
00391         }
00392     KShortcutDialog::accept();
00393     }
00394 
00395 // Workaround for Qt bug causing #119142 - wheel event causes only calling
00396 // of hide() but not close(), so dialog closing is not performed.
00397 // Possible recursive calling close->hide->close should be fine, as close()
00398 // has checks against that.
00399 void ShortcutDialog::hide()
00400     {
00401     close();
00402     return KShortcutDialog::hide();
00403     }
00404 
00405 #endif
00406 
00407 
00408 } // namespace
00409 
00410 #ifndef KCMRULES
00411 #include "utils.moc"
00412 #endif

kwin

Skip menu "kwin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kwin

Skip menu "kwin"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for kwin by doxygen 1.6.3
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |