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