00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00084 if ( hints->flags & MWM_HINTS_FUNCTIONS )
00085 {
00086
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
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
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;
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
00198 switch ( event->type ) {
00199 case ButtonPress:
00200
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
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
00230
00231
00232
00233
00234
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;
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 {
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
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;
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
00418
00419 widget->setCheckForConflictsAgainst(KKeySequenceWidget::None);
00420
00421 widget->setMultiKeyShortcutsAllowed(false);
00422
00423
00424 connect(
00425 widget, SIGNAL(keySequenceChanged(const QKeySequence&)),
00426 SLOT(keySequenceChanged(const QKeySequence&)));
00427
00428 setMainWidget( widget );
00429
00430
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 {
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
00467 QList<KGlobalShortcutInfo> conflicting = KGlobalAccel::getGlobalShortcutsByKey(seq);
00468 if (!conflicting.isEmpty()) {
00469 kDebug(1212) << "TODO: Display conflicting shortcuts to user";
00470
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 }
00483
00484 #ifndef KCMRULES
00485 #include "utils.moc"
00486 #endif