00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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>
00040 #include <kwinmodule.h>
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>
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>
00055 #include <X11/Xutil.h>
00056 #include <X11/Xatom.h>
00057 #endif
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
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;
00094 int frameStyle;
00095 int lineWidth;
00096 int margin;
00097 bool fallback_mode;
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
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_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();
00220 resize( sizeHint());
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
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;
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
00259 setTopLevelMenuInternal( d->topLevel );
00260 }
00261 }
00262 else
00263 {
00264 if( parentWidget() && obj == parentWidget()->topLevelWidget())
00265 {
00266 if( ev->type() == QEvent::ShowNormal )
00267 setTopLevelMenuInternal( d->wasTopLevel );
00268 }
00269 }
00270 return QMenuBar::eventFilter( obj, ev );
00271 }
00272
00273
00274 void KMenuBar::showEvent( QShowEvent *e )
00275 {
00276 QMenuBar::showEvent(e);
00277 }
00278
00279 void KMenuBar::updateFallbackSize()
00280 {
00281 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00282 if( !d->topLevel )
00283 return;
00284 if( d->selection->owner() != None )
00285 {
00286
00287 d->selection_timer.stop();
00288 if( d->fallback_mode )
00289 {
00290 d->fallback_mode = false;
00291
00292 #endif
00293 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00294 menuContentsChanged();
00295 resize( sizeHint());
00296 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00297 }
00298 return;
00299 }
00300 if( d->selection_timer.isActive())
00301 return;
00302 d->selection_timer.start( 100, true );
00303 #endif
00304 }
00305
00306 void KMenuBar::selectionTimeout()
00307 {
00308 if ( d->topLevel )
00309 {
00310 d->fallback_mode = true;
00311 KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama");
00312 int screen = xineramaConfig.readNumEntry("MenubarScreen",
00313 QApplication::desktop()->screenNumber(QPoint(0,0)) );
00314 QRect area = QApplication::desktop()->screenGeometry(screen);
00315 #if QT_VERSION < 0x030200
00316 int margin = frameWidth() + 2;
00317 #else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2
00318 int margin = 0;
00319 #endif
00320 move(area.left() - margin, area.top() - margin);
00321 setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
00322 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00323 int strut_height = height() - margin;
00324 if( strut_height < 0 )
00325 strut_height = 0;
00326 KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00327 #endif
00328 }
00329 }
00330
00331 int KMenuBar::block_resize = 0;
00332
00333 void KMenuBar::resizeEvent( QResizeEvent *e )
00334 {
00335 if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00336 {
00337 ++block_resize;
00338 QMenuBar::resizeEvent(e);
00339 --block_resize;
00340 }
00341 else
00342 QMenuBar::resizeEvent(e);
00343 }
00344
00345 void KMenuBar::setGeometry( const QRect& r )
00346 {
00347 setGeometry( r.x(), r.y(), r.width(), r.height() );
00348 }
00349
00350 void KMenuBar::setGeometry( int x, int y, int w, int h )
00351 {
00352 if( block_resize > 0 )
00353 {
00354 move( x, y );
00355 return;
00356 }
00357 checkSize( w, h );
00358 if( geometry() != QRect( x, y, w, h ))
00359 QMenuBar::setGeometry( x, y, w, h );
00360 }
00361
00362 void KMenuBar::resize( int w, int h )
00363 {
00364 if( block_resize > 0 )
00365 return;
00366 checkSize( w, h );
00367 if( size() != QSize( w, h ))
00368 QMenuBar::resize( w, h );
00369
00370 }
00371
00372 void KMenuBar::checkSize( int& w, int& h )
00373 {
00374 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00375 if( !d->topLevel || d->fallback_mode )
00376 return;
00377 #endif
00378 if( parentWidget() && parentWidget()->width() == w )
00379 {
00380
00381
00382
00383 ++block_resize;
00384 QSize s = sizeHint();
00385 w = s.width();
00386 h = s.height();
00387 --block_resize;
00388 }
00389
00390
00391
00392 w = KMAX( w, d->min_size.width());
00393 h = KMAX( h, d->min_size.height());
00394 }
00395
00396 bool KMenuBar::x11Event( XEvent* ev )
00397 {
00398 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00399 if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
00400 && ev->xclient.window == winId())
00401 {
00402
00403
00404
00405
00406 d->min_size = QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
00407
00408 menuContentsChanged();
00409 resize( sizeHint());
00410 return true;
00411 }
00412 #endif
00413 return QMenuBar::x11Event( ev );
00414 }
00415
00416 void KMenuBar::setFrameStyle( int style )
00417 {
00418 if( d->topLevel )
00419 d->frameStyle = style;
00420 else
00421 QMenuBar::setFrameStyle( style );
00422 }
00423
00424 void KMenuBar::setLineWidth( int width )
00425 {
00426 if( d->topLevel )
00427 d->lineWidth = width;
00428 else
00429 QMenuBar::setLineWidth( width );
00430 }
00431
00432 void KMenuBar::setMargin( int margin )
00433 {
00434 if( d->topLevel )
00435 d->margin = margin;
00436 else
00437 QMenuBar::setMargin( margin );
00438 }
00439
00440 void KMenuBar::virtual_hook( int, void* )
00441 { }
00442
00443 #include "kmenubar.moc"