• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWin

utils.cpp

Go to the documentation of this file.
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 This program is free software; you can redistribute it and/or modify
00009 it under the terms of the GNU General Public License as published by
00010 the Free Software Foundation; either version 2 of the License, or
00011 (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 GNU General Public License for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00020 *********************************************************************/
00021 
00022 /*
00023 
00024  This file is for (very) small utility functions/classes.
00025 
00026 */
00027 
00028 #include "utils.h"
00029 
00030 #include <unistd.h>
00031 
00032 #ifndef KCMRULES
00033 
00034 #include <kxerrorhandler.h>
00035 #include <assert.h>
00036 #include <kdebug.h>
00037 #include <kshortcut.h>
00038 #include <kkeyserver.h>
00039 
00040 #include <X11/Xlib.h>
00041 #include <X11/extensions/shape.h>
00042 #include <X11/Xatom.h>
00043 #include <QX11Info>
00044 
00045 #include <stdio.h>
00046 
00047 #include "atoms.h"
00048 #include "notifications.h"
00049 #include "workspace.h"
00050 
00051 #endif
00052 
00053 namespace KWin
00054 {
00055 
00056 #ifndef KCMRULES
00057 
00058 void Motif::readFlags( WId w, bool& noborder, bool& resize, bool& move,
00059     bool& minimize, bool& maximize, bool& close )
00060     {
00061     Atom type;
00062     int format;
00063     unsigned long length, after;
00064     unsigned char* data;
00065     MwmHints* hints = 0;
00066     if ( XGetWindowProperty( display(), w, atoms->motif_wm_hints, 0, 5,
00067                              false, atoms->motif_wm_hints, &type, &format,
00068                              &length, &after, &data ) == Success ) 
00069         {
00070         if ( data )
00071             hints = (MwmHints*) data;
00072         }
00073     noborder = false;
00074     resize = true;
00075     move = true;
00076     minimize = true;
00077     maximize = true;
00078     close = true;
00079     if ( hints ) 
00080         {
00081     // To quote from Metacity 'We support those MWM hints deemed non-stupid'
00082         if ( hints->flags & MWM_HINTS_FUNCTIONS ) 
00083             {
00084             // if MWM_FUNC_ALL is set, other flags say what to turn _off_
00085             bool set_value = (( hints->functions & MWM_FUNC_ALL ) == 0 );
00086             resize = move = minimize = maximize = close = !set_value;
00087             if( hints->functions & MWM_FUNC_RESIZE )
00088                 resize = set_value;
00089             if( hints->functions & MWM_FUNC_MOVE )
00090                 move = set_value;
00091             if( hints->functions & MWM_FUNC_MINIMIZE )
00092                 minimize = set_value;
00093             if( hints->functions & MWM_FUNC_MAXIMIZE )
00094                 maximize = set_value;
00095             if( hints->functions & MWM_FUNC_CLOSE )
00096                 close = set_value;
00097             }
00098         if ( hints->flags & MWM_HINTS_DECORATIONS ) 
00099             {
00100             if ( hints->decorations == 0 )
00101                 noborder = true;
00102             }
00103         XFree( data );
00104         }
00105     }
00106 
00107 //************************************
00108 // KWinSelectionOwner
00109 //************************************
00110 
00111 KWinSelectionOwner::KWinSelectionOwner( int screen_P )
00112     : KSelectionOwner( make_selection_atom( screen_P ), screen_P )
00113     {
00114     }
00115 
00116 Atom KWinSelectionOwner::make_selection_atom( int screen_P )
00117     {
00118     if( screen_P < 0 )
00119         screen_P = DefaultScreen( display());
00120     char tmp[ 30 ];
00121     sprintf( tmp, "WM_S%d", screen_P );
00122     return XInternAtom( display(), tmp, False );
00123     }
00124 
00125 void KWinSelectionOwner::getAtoms()
00126     {
00127     KSelectionOwner::getAtoms();
00128     if( xa_version == None )
00129         {
00130         Atom atoms[ 1 ];
00131         const char* const names[] =
00132             { "VERSION" };
00133         XInternAtoms( display(), const_cast< char** >( names ), 1, False, atoms );
00134         xa_version = atoms[ 0 ];
00135         }
00136     }
00137 
00138 void KWinSelectionOwner::replyTargets( Atom property_P, Window requestor_P )
00139     {
00140     KSelectionOwner::replyTargets( property_P, requestor_P );
00141     Atom atoms[ 1 ] = { xa_version };
00142     // PropModeAppend !
00143     XChangeProperty( display(), requestor_P, property_P, XA_ATOM, 32, PropModeAppend,
00144         reinterpret_cast< unsigned char* >( atoms ), 1 );
00145     }
00146 
00147 bool KWinSelectionOwner::genericReply( Atom target_P, Atom property_P, Window requestor_P )
00148     {
00149     if( target_P == xa_version )
00150         {
00151         long version[] = { 2, 0 };
00152         XChangeProperty( display(), requestor_P, property_P, XA_INTEGER, 32,
00153             PropModeReplace, reinterpret_cast< unsigned char* >( &version ), 2 );
00154         }
00155     else
00156         return KSelectionOwner::genericReply( target_P, property_P, requestor_P );
00157     return true;    
00158     }
00159 
00160 Atom KWinSelectionOwner::xa_version = None;
00161 
00162 
00163 QByteArray getStringProperty(WId w, Atom prop, char separator)
00164     {
00165     Atom type;
00166     int format, status;
00167     unsigned long nitems = 0;
00168     unsigned long extra = 0;
00169     unsigned char *data = 0;
00170     QByteArray result = "";
00171     KXErrorHandler handler; // ignore errors
00172     status = XGetWindowProperty( display(), w, prop, 0, 10000,
00173                                  false, XA_STRING, &type, &format,
00174                                  &nitems, &extra, &data );
00175     if ( status == Success) 
00176         {
00177         if (data && separator) 
00178             {
00179             for (int i=0; i<(int)nitems; i++)
00180                 if (!data[i] && i+1<(int)nitems)
00181                     data[i] = separator;
00182             }
00183         if (data)
00184             result = (const char*) data;
00185         XFree(data);
00186         }
00187     return result;
00188     }
00189 
00190 static Time next_x_time;
00191 static Bool update_x_time_predicate( Display*, XEvent* event, XPointer )
00192 {
00193     if( next_x_time != CurrentTime )
00194         return False;
00195     // from qapplication_x11.cpp
00196     switch ( event->type ) {
00197     case ButtonPress:
00198     // fallthrough intended
00199     case ButtonRelease:
00200     next_x_time = event->xbutton.time;
00201     break;
00202     case MotionNotify:
00203     next_x_time = event->xmotion.time;
00204     break;
00205     case KeyPress:
00206     // fallthrough intended
00207     case KeyRelease:
00208     next_x_time = event->xkey.time;
00209     break;
00210     case PropertyNotify:
00211     next_x_time = event->xproperty.time;
00212     break;
00213     case EnterNotify:
00214     case LeaveNotify:
00215     next_x_time = event->xcrossing.time;
00216     break;
00217     case SelectionClear:
00218     next_x_time = event->xselectionclear.time;
00219     break;
00220     default:
00221     break;
00222     }
00223     return False;
00224 }
00225 
00226 /*
00227  Updates xTime(). This used to simply fetch current timestamp from the server,
00228  but that can cause xTime() to be newer than timestamp of events that are
00229  still in our events queue, thus e.g. making XSetInputFocus() caused by such
00230  event to be ignored. Therefore events queue is searched for first
00231  event with timestamp, and extra PropertyNotify is generated in order to make
00232  sure such event is found.
00233 */
00234 void updateXTime()
00235     {
00236     static QWidget* w = 0;
00237     if ( !w )
00238         w = new QWidget;
00239     long data = 1;
00240     XChangeProperty(display(), w->winId(), atoms->kwin_running, atoms->kwin_running, 32,
00241                     PropModeAppend, (unsigned char*) &data, 1);
00242     next_x_time = CurrentTime;
00243     XEvent dummy;
00244     XCheckIfEvent( display(), &dummy, update_x_time_predicate, NULL );
00245     if( next_x_time == CurrentTime )
00246         {
00247         XSync( display(), False );
00248         XCheckIfEvent( display(), &dummy, update_x_time_predicate, NULL );
00249         }
00250     assert( next_x_time != CurrentTime );
00251     QX11Info::setAppTime( next_x_time );
00252     XEvent ev; // remove the PropertyNotify event from the events queue
00253     XWindowEvent( display(), w->winId(), PropertyChangeMask, &ev );
00254     }
00255 
00256 static int server_grab_count = 0;
00257 
00258 void grabXServer()
00259     {
00260     if( ++server_grab_count == 1 )
00261         XGrabServer( display());
00262     }
00263 
00264 void ungrabXServer()
00265     {
00266     assert( server_grab_count > 0 );
00267     if( --server_grab_count == 0 )
00268         {
00269         XUngrabServer( display());
00270         XFlush( display());
00271         Notify::sendPendingEvents();
00272         }
00273     }
00274 
00275 bool grabbedXServer()
00276     {
00277     return server_grab_count > 0;
00278     }
00279 
00280 static bool keyboard_grabbed = false;
00281 
00282 bool grabXKeyboard( Window w )
00283     {
00284     if( QWidget::keyboardGrabber() != NULL )
00285         return false;
00286     if( keyboard_grabbed )
00287         return false;
00288     if( qApp->activePopupWidget() != NULL )
00289         return false;
00290     if( w == None )
00291         w = rootWindow();
00292     if( XGrabKeyboard( display(), w, False,
00293         GrabModeAsync, GrabModeAsync, xTime()) != GrabSuccess )
00294         return false;
00295     keyboard_grabbed = true;
00296     return true;
00297     }
00298 
00299 void ungrabXKeyboard()
00300     {
00301     if( !keyboard_grabbed )
00302         { // grabXKeyboard() may fail sometimes, so don't fail, but at least warn anyway
00303         kDebug() << "ungrabXKeyboard() called but keyboard not grabbed!";
00304         }
00305     keyboard_grabbed = false;
00306     XUngrabKeyboard( display(), xTime());
00307     }
00308 
00309 QPoint cursorPos()
00310     {
00311     return Workspace::self()->cursorPos();
00312     }
00313 
00314 // converting between X11 mouse/keyboard state mask and Qt button/keyboard states
00315 
00316 int qtToX11Button( Qt::MouseButton button )
00317     {
00318     if( button == Qt::LeftButton )
00319         return Button1;
00320     else if( button == Qt::MidButton )
00321         return Button2;
00322     else if( button == Qt::RightButton )
00323         return Button3;
00324     return AnyButton; // 0
00325     }
00326 
00327 Qt::MouseButton x11ToQtMouseButton( int button )
00328     {
00329     if( button == Button1 )
00330         return Qt::LeftButton;
00331     if( button == Button2 )
00332         return Qt::MidButton;
00333     if( button == Button3 )
00334         return Qt::RightButton;
00335     return Qt::NoButton;
00336     }
00337 
00338 int qtToX11State( Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers )
00339     {
00340     int ret = 0;
00341     if( buttons & Qt::LeftButton )
00342         ret |= Button1Mask;
00343     if( buttons & Qt::MidButton )
00344         ret |= Button2Mask;
00345     if( buttons & Qt::RightButton )
00346         ret |= Button3Mask;
00347     if( modifiers & Qt::ShiftModifier )
00348         ret |= ShiftMask;
00349     if( modifiers & Qt::ControlModifier )
00350         ret |= ControlMask;
00351     if( modifiers & Qt::AltModifier )
00352         ret |= KKeyServer::modXAlt();
00353     if( modifiers & Qt::MetaModifier )
00354         ret |= KKeyServer::modXMeta();
00355     return ret;
00356     }
00357 
00358 Qt::MouseButtons x11ToQtMouseButtons( int state )
00359     {
00360     Qt::MouseButtons ret = 0;
00361     if( state & Button1Mask )
00362         ret |= Qt::LeftButton;
00363     if( state & Button2Mask )
00364         ret |= Qt::MidButton;
00365     if( state & Button3Mask )
00366         ret |= Qt::RightButton;
00367     return ret;
00368     }
00369 
00370 Qt::KeyboardModifiers x11ToQtKeyboardModifiers( int state )
00371     {
00372     Qt::KeyboardModifiers ret = 0;
00373     if( state & ShiftMask )
00374         ret |= Qt::ShiftModifier;
00375     if( state & ControlMask )
00376         ret |= Qt::ControlModifier;
00377     if( state & KKeyServer::modXAlt())
00378         ret |= Qt::AltModifier;
00379     if( state & KKeyServer::modXMeta())
00380         ret |= Qt::MetaModifier;
00381     return ret;
00382     }
00383 
00384 #endif
00385 
00386 bool isLocalMachine( const QByteArray& host )
00387     {
00388 #ifdef HOST_NAME_MAX
00389     char hostnamebuf[HOST_NAME_MAX];
00390 #else
00391     char hostnamebuf[256];
00392 #endif
00393     if (gethostname (hostnamebuf, sizeof hostnamebuf) >= 0) 
00394         {
00395         hostnamebuf[sizeof(hostnamebuf)-1] = 0;
00396         if (host == hostnamebuf)
00397             return true;
00398         if( char *dot = strchr(hostnamebuf, '.'))
00399             {
00400             *dot = '\0';
00401             if( host == hostnamebuf )
00402                 return true;
00403             }
00404         }
00405     return false;
00406     }
00407 
00408 #ifndef KCMRULES
00409 ShortcutDialog::ShortcutDialog( const QKeySequence& cut )
00410     : widget( new KKeySequenceWidget( this ))
00411     {
00412     widget->setKeySequence( cut );
00413     // make it a popup, so that it has the grab
00414     XSetWindowAttributes attrs;
00415     attrs.override_redirect = True;
00416     XChangeWindowAttributes( display(), winId(), CWOverrideRedirect, &attrs );
00417     setWindowFlags( Qt::Popup );
00418     }
00419 
00420 void ShortcutDialog::accept()
00421     {
00422     QKeySequence seq = shortcut();
00423     if( !seq.isEmpty())
00424         {
00425         if( seq[0] == Qt::Key_Escape )
00426             {
00427             reject();
00428             return;
00429             }
00430         if( seq[0] == Qt::Key_Space
00431             || (seq[0] & Qt::KeyboardModifierMask) == 0 )
00432             { // clear
00433             widget->clearKeySequence();
00434             KDialog::accept();
00435             return;
00436             }
00437         }
00438     KDialog::accept();
00439     }
00440 
00441 void ShortcutDialog::done( int r )
00442     {
00443     KDialog::done( r );
00444     emit dialogDone( r == Accepted );
00445     }
00446 
00447 QKeySequence ShortcutDialog::shortcut() const
00448     {
00449     return widget->keySequence();
00450     }
00451 
00452 #endif //KCMRULES
00453 } // namespace
00454 
00455 #ifndef KCMRULES
00456 #include "utils.moc"
00457 #endif

KWin

Skip menu "KWin"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal