kdeui Library API Documentation

kmenubar.cpp

00001 /* 00002 00003 Copyright (C) 1997, 1998, 1999, 2000 Sven Radej (radej@kde.org) 00004 Copyright (C) 1997, 1998, 1999, 2000 Matthias Ettrich (ettrich@kde.org) 00005 Copyright (C) 1999, 2000 Daniel "Mosfet" Duley (mosfet@kde.org) 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 #ifndef INCLUDE_MENUITEM_DEF 00025 #define INCLUDE_MENUITEM_DEF 00026 #endif 00027 00028 #include "config.h" 00029 #include <qevent.h> 00030 #include <qobjectlist.h> 00031 #include <qaccel.h> 00032 00033 #include <kconfig.h> 00034 #include <kglobalsettings.h> 00035 #include <kmenubar.h> 00036 #include <kapplication.h> 00037 00038 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00039 #include <kwin.h> // schroder 00040 #include <kwinmodule.h> // schroder 00041 #endif 00042 00043 #include <kglobal.h> 00044 #include <kdebug.h> 00045 00046 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00047 #include <qxembed.h> // schroder 00048 #endif 00049 00050 #include <kmanagerselection.h> 00051 #include <qtimer.h> 00052 00053 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00054 #include <X11/Xlib.h> // schroder 00055 #include <X11/Xutil.h> // schroder 00056 #include <X11/Xatom.h> // schroder 00057 #endif 00058 00059 /* 00060 00061 Toplevel menubar (not for the fallback size handling done by itself): 00062 - should not alter position or set strut 00063 - every toplevel must have at most one matching topmenu 00064 - embedder won't allow shrinking below a certain size 00065 - must have WM_TRANSIENT_FOR pointing the its mainwindow 00066 - the exception is desktop's menubar, which can be transient for root window 00067 because of using root window as the desktop window 00068 - Fitts' Law 00069 00070 */ 00071 00072 class KMenuBar::KMenuBarPrivate 00073 { 00074 public: 00075 KMenuBarPrivate() 00076 : forcedTopLevel( false ), 00077 topLevel( false ), 00078 wasTopLevel( false ), 00079 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00080 selection( NULL ), 00081 #endif 00082 min_size( 0, 0 ) 00083 { 00084 } 00085 ~KMenuBarPrivate() 00086 { 00087 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00088 delete selection; 00089 #endif 00090 } 00091 bool forcedTopLevel; 00092 bool topLevel; 00093 bool wasTopLevel; // when TLW is fullscreen, remember state 00094 int frameStyle; // only valid in toplevel mode 00095 int lineWidth; // dtto 00096 int margin; // dtto 00097 bool fallback_mode; // dtto 00098 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00099 KSelectionWatcher* selection; 00100 #endif 00101 QTimer selection_timer; 00102 QSize min_size; 00103 static Atom makeSelectionAtom(); 00104 }; 00105 00106 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00107 static Atom selection_atom = None; 00108 static Atom msg_type_atom = None; 00109 00110 static 00111 void initAtoms() 00112 { 00113 char nm[ 100 ]; 00114 sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay())); 00115 char nm2[] = "_KDE_TOPMENU_MINSIZE"; 00116 char* names[ 2 ] = { nm, nm2 }; 00117 Atom atoms[ 2 ]; 00118 XInternAtoms( qt_xdisplay(), names, 2, False, atoms ); 00119 selection_atom = atoms[ 0 ]; 00120 msg_type_atom = atoms[ 1 ]; 00121 } 00122 #endif 00123 00124 Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom() 00125 { 00126 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00127 if( selection_atom == None ) 00128 initAtoms(); 00129 return selection_atom; 00130 #else 00131 return 0; 00132 #endif 00133 } 00134 00135 KMenuBar::KMenuBar(QWidget *parent, const char *name) 00136 : QMenuBar(parent, name) 00137 { 00138 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00139 QXEmbed::initialize(); 00140 #endif 00141 d = new KMenuBarPrivate; 00142 connect( &d->selection_timer, SIGNAL( timeout()), 00143 this, SLOT( selectionTimeout())); 00144 00145 #if (QT_VERSION-0 >= 0x030200) // XRANDR support 00146 connect( qApp->desktop(), SIGNAL( resized( int )), SLOT( updateFallbackSize())); 00147 #endif 00148 00149 if ( kapp ) 00150 // toolbarAppearanceChanged(int) is sent when changing macstyle 00151 connect( kapp, SIGNAL(toolbarAppearanceChanged(int)), 00152 this, SLOT(slotReadConfig())); 00153 00154 slotReadConfig(); 00155 } 00156 00157 KMenuBar::~KMenuBar() 00158 { 00159 delete d; 00160 } 00161 00162 void KMenuBar::setTopLevelMenu(bool top_level) 00163 { 00164 d->forcedTopLevel = top_level; 00165 setTopLevelMenuInternal( top_level ); 00166 } 00167 00168 void KMenuBar::setTopLevelMenuInternal(bool top_level) 00169 { 00170 if (d->forcedTopLevel) 00171 top_level = true; 00172 00173 d->wasTopLevel = top_level; 00174 if( parentWidget() 00175 && parentWidget()->topLevelWidget()->isFullScreen()) 00176 top_level = false; 00177 00178 if ( isTopLevelMenu() == top_level ) 00179 return; 00180 d->topLevel = top_level; 00181 if ( isTopLevelMenu() ) 00182 { 00183 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00184 d->selection = new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(), 00185 DefaultScreen( qt_xdisplay())); 00186 connect( d->selection, SIGNAL( newOwner( Window )), 00187 this, SLOT( updateFallbackSize())); 00188 connect( d->selection, SIGNAL( lostOwner()), 00189 this, SLOT( updateFallbackSize())); 00190 #endif 00191 d->frameStyle = frameStyle(); 00192 d->lineWidth = lineWidth(); 00193 d->margin = margin(); 00194 d->fallback_mode = false; 00195 bool wasShown = !isHidden(); 00196 reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder, QPoint(0,0), false ); 00197 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME 00198 KWin::setType( winId(), NET::TopMenu ); 00199 #endif 00200 QMenuBar::setFrameStyle( NoFrame ); 00201 QMenuBar::setLineWidth( 0 ); 00202 QMenuBar::setMargin( 0 ); 00203 updateFallbackSize(); 00204 d->min_size = QSize( 0, 0 ); 00205 if ( wasShown ) 00206 show(); 00207 } else 00208 { 00209 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00210 delete d->selection; 00211 d->selection = NULL; 00212 #endif 00213 setBackgroundMode( PaletteButton ); 00214 setFrameStyle( d->frameStyle ); 00215 setLineWidth( d->lineWidth ); 00216 setMargin( d->margin ); 00217 setMinimumSize( 0, 0 ); 00218 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); 00219 menuContentsChanged(); // trigger invalidating calculated size 00220 resize( sizeHint()); // and resize to preferred size 00221 if ( parentWidget() ) 00222 reparent( parentWidget(), QPoint(0,0), !isHidden()); 00223 } 00224 } 00225 00226 bool KMenuBar::isTopLevelMenu() const 00227 { 00228 return d->topLevel; 00229 } 00230 00231 // KDE4 remove 00232 void KMenuBar::show() 00233 { 00234 QMenuBar::show(); 00235 } 00236 00237 void KMenuBar::slotReadConfig() 00238 { 00239 KConfig *config = KGlobal::config(); 00240 KConfigGroupSaver saver( config, "KDE" ); 00241 setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) ); 00242 } 00243 00244 bool KMenuBar::eventFilter(QObject *obj, QEvent *ev) 00245 { 00246 if ( d->topLevel ) 00247 { 00248 if ( parentWidget() && obj == parentWidget()->topLevelWidget() ) 00249 { 00250 if( ev->type() == QEvent::Resize ) 00251 return false; // ignore resizing of parent, QMenuBar would try to adjust size 00252 if ( ev->type() == QEvent::Accel || ev->type() == QEvent::AccelAvailable ) 00253 { 00254 if ( QApplication::sendEvent( topLevelWidget(), ev ) ) 00255 return true; 00256 } 00257 if(ev->type() == QEvent::ShowFullScreen ) 00258 // will update the state properly 00259 setTopLevelMenuInternal( d->topLevel ); 00260 } 00261 } 00262 else 00263 { 00264 if( parentWidget() && obj == parentWidget()->topLevelWidget()) 00265 { 00266 #if QT_VERSION >= 0x030300 00267 if( ev->type() == QEvent::WindowStateChange 00268 #else 00269 if( ( ev->type() == QEvent::ShowNormal || ev->type() == QEvent::ShowMaximized ) 00270 #endif 00271 && !parentWidget()->topLevelWidget()->isFullScreen() ) 00272 setTopLevelMenuInternal( d->wasTopLevel ); 00273 } 00274 } 00275 return QMenuBar::eventFilter( obj, ev ); 00276 } 00277 00278 // KDE4 remove 00279 void KMenuBar::showEvent( QShowEvent *e ) 00280 { 00281 QMenuBar::showEvent(e); 00282 } 00283 00284 void KMenuBar::updateFallbackSize() 00285 { 00286 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00287 if( !d->topLevel ) 00288 return; 00289 if( d->selection->owner() != None ) 00290 { // somebody is managing us, don't mess anything, undo changes 00291 // done in fallback mode if needed 00292 d->selection_timer.stop(); 00293 if( d->fallback_mode ) 00294 { 00295 d->fallback_mode = false; 00296 // KWin::setStrut( winId(), 0, 0, 0, 0 ); KWin will set strut as it will see fit 00297 #endif 00298 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX ); 00299 menuContentsChanged(); 00300 resize( sizeHint()); 00301 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00302 } 00303 return; 00304 } 00305 if( d->selection_timer.isActive()) 00306 return; 00307 d->selection_timer.start( 100, true ); 00308 #endif 00309 } 00310 00311 void KMenuBar::selectionTimeout() 00312 { // nobody is managing us, handle resizing 00313 if ( d->topLevel ) 00314 { 00315 d->fallback_mode = true; // KMenuBar is handling its position itself 00316 KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama"); 00317 int screen = xineramaConfig.readNumEntry("MenubarScreen", 00318 QApplication::desktop()->screenNumber(QPoint(0,0)) ); 00319 QRect area = QApplication::desktop()->screenGeometry(screen); 00320 #if QT_VERSION < 0x030200 00321 int margin = frameWidth() + 2; 00322 #else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2 00323 int margin = 0; 00324 #endif 00325 move(area.left() - margin, area.top() - margin); 00326 setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) ); 00327 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME 00328 int strut_height = height() - margin; 00329 if( strut_height < 0 ) 00330 strut_height = 0; 00331 KWin::setStrut( winId(), 0, 0, strut_height, 0 ); 00332 #endif 00333 } 00334 } 00335 00336 int KMenuBar::block_resize = 0; 00337 00338 void KMenuBar::resizeEvent( QResizeEvent *e ) 00339 { 00340 if( e->spontaneous() && d->topLevel && !d->fallback_mode ) 00341 { 00342 ++block_resize; // do not respond with configure request to ConfigureNotify event 00343 QMenuBar::resizeEvent(e); // to avoid possible infinite loop 00344 --block_resize; 00345 } 00346 else 00347 QMenuBar::resizeEvent(e); 00348 } 00349 00350 void KMenuBar::setGeometry( const QRect& r ) 00351 { 00352 setGeometry( r.x(), r.y(), r.width(), r.height() ); 00353 } 00354 00355 void KMenuBar::setGeometry( int x, int y, int w, int h ) 00356 { 00357 if( block_resize > 0 ) 00358 { 00359 move( x, y ); 00360 return; 00361 } 00362 checkSize( w, h ); 00363 if( geometry() != QRect( x, y, w, h )) 00364 QMenuBar::setGeometry( x, y, w, h ); 00365 } 00366 00367 void KMenuBar::resize( int w, int h ) 00368 { 00369 if( block_resize > 0 ) 00370 return; 00371 checkSize( w, h ); 00372 if( size() != QSize( w, h )) 00373 QMenuBar::resize( w, h ); 00374 // kdDebug() << "RS:" << w << ":" << h << ":" << width() << ":" << height() << ":" << minimumWidth() << ":" << minimumHeight() << endl; 00375 } 00376 00377 void KMenuBar::checkSize( int& w, int& h ) 00378 { 00379 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00380 if( !d->topLevel || d->fallback_mode ) 00381 return; 00382 #endif 00383 if( parentWidget() && parentWidget()->width() == w ) 00384 { // Menubar is possibly being attempted to be resized to match 00385 // mainwindow size. Resize to sizeHint() instead. Since 00386 // sizeHint() may indirectly call resize(), avoid infinite 00387 // recursion. 00388 ++block_resize; 00389 QSize s = sizeHint(); 00390 w = s.width(); 00391 h = s.height(); 00392 --block_resize; 00393 } 00394 // This is not done as setMinimumSize(), becase that would set the minimum 00395 // size in WM_NORMAL_HINTS, and KWin would not allow changing to smaller size 00396 // anymore 00397 w = KMAX( w, d->min_size.width()); 00398 h = KMAX( h, d->min_size.height()); 00399 } 00400 00401 bool KMenuBar::x11Event( XEvent* ev ) 00402 { 00403 #if defined Q_WS_X11 && ! defined K_WS_QTONLY 00404 if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom 00405 && ev->xclient.window == winId()) 00406 { 00407 // QMenuBar is trying really hard to keep the size it deems right. 00408 // Forcing minimum size and blocking resizing to match parent size 00409 // in checkResizingToParent() seem to be the only way to make 00410 // KMenuBar keep the size it wants 00411 d->min_size = QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] ); 00412 // kdDebug() << "MINSIZE:" << d->min_size << endl; 00413 menuContentsChanged(); 00414 resize( sizeHint()); 00415 return true; 00416 } 00417 #endif 00418 return QMenuBar::x11Event( ev ); 00419 } 00420 00421 void KMenuBar::setFrameStyle( int style ) 00422 { 00423 if( d->topLevel ) 00424 d->frameStyle = style; 00425 else 00426 QMenuBar::setFrameStyle( style ); 00427 } 00428 00429 void KMenuBar::setLineWidth( int width ) 00430 { 00431 if( d->topLevel ) 00432 d->lineWidth = width; 00433 else 00434 QMenuBar::setLineWidth( width ); 00435 } 00436 00437 void KMenuBar::setMargin( int margin ) 00438 { 00439 if( d->topLevel ) 00440 d->margin = margin; 00441 else 00442 QMenuBar::setMargin( margin ); 00443 } 00444 00445 void KMenuBar::closeEvent( QCloseEvent* e ) 00446 { 00447 if( d->topLevel ) 00448 e->ignore(); // mainly for the fallback mode 00449 else 00450 QMenuBar::closeEvent( e ); 00451 } 00452 00453 void KMenuBar::virtual_hook( int, void* ) 00454 { /*BASE::virtual_hook( id, data );*/ } 00455 00456 #include "kmenubar.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 20 09:48:45 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003