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 #include <qpainter.h>
00033 #include <qstyle.h>
00034
00035 #include <kconfig.h>
00036 #include <kglobalsettings.h>
00037 #include <kmenubar.h>
00038 #include <kapplication.h>
00039
00040 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00041 #include <kwin.h>
00042 #include <kwinmodule.h>
00043 #endif
00044
00045 #include <kglobal.h>
00046 #include <kdebug.h>
00047
00048 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00049 #include <qxembed.h>
00050 #endif
00051
00052 #include <kmanagerselection.h>
00053 #include <qtimer.h>
00054
00055 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00056 #include <X11/Xlib.h>
00057 #include <X11/Xutil.h>
00058 #include <X11/Xatom.h>
00059 #endif
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 class KMenuBar::KMenuBarPrivate
00075 {
00076 public:
00077 KMenuBarPrivate()
00078 : forcedTopLevel( false ),
00079 topLevel( false ),
00080 wasTopLevel( false ),
00081 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00082 selection( NULL ),
00083 #endif
00084 min_size( 0, 0 )
00085 {
00086 }
00087 ~KMenuBarPrivate()
00088 {
00089 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00090 delete selection;
00091 #endif
00092 }
00093 bool forcedTopLevel;
00094 bool topLevel;
00095 bool wasTopLevel;
00096 int frameStyle;
00097 int lineWidth;
00098 int margin;
00099 bool fallback_mode;
00100 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00101 KSelectionWatcher* selection;
00102 #endif
00103 QTimer selection_timer;
00104 QSize min_size;
00105 static Atom makeSelectionAtom();
00106 };
00107
00108 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00109 static Atom selection_atom = None;
00110 static Atom msg_type_atom = None;
00111
00112 static
00113 void initAtoms()
00114 {
00115 char nm[ 100 ];
00116 sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
00117 char nm2[] = "_KDE_TOPMENU_MINSIZE";
00118 char* names[ 2 ] = { nm, nm2 };
00119 Atom atoms[ 2 ];
00120 XInternAtoms( qt_xdisplay(), names, 2, False, atoms );
00121 selection_atom = atoms[ 0 ];
00122 msg_type_atom = atoms[ 1 ];
00123 }
00124 #endif
00125
00126 Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom()
00127 {
00128 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00129 if( selection_atom == None )
00130 initAtoms();
00131 return selection_atom;
00132 #else
00133 return 0;
00134 #endif
00135 }
00136
00137 KMenuBar::KMenuBar(QWidget *parent, const char *name)
00138 : QMenuBar(parent, name)
00139 {
00140 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00141 QXEmbed::initialize();
00142 #endif
00143 d = new KMenuBarPrivate;
00144 connect( &d->selection_timer, SIGNAL( timeout()),
00145 this, SLOT( selectionTimeout()));
00146
00147 #if (QT_VERSION-0 >= 0x030200) // XRANDR support
00148 connect( qApp->desktop(), SIGNAL( resized( int )), SLOT( updateFallbackSize()));
00149 #endif
00150
00151 if ( kapp )
00152
00153 connect( kapp, SIGNAL(toolbarAppearanceChanged(int)),
00154 this, SLOT(slotReadConfig()));
00155
00156 slotReadConfig();
00157 }
00158
00159 KMenuBar::~KMenuBar()
00160 {
00161 delete d;
00162 }
00163
00164 void KMenuBar::setTopLevelMenu(bool top_level)
00165 {
00166 d->forcedTopLevel = top_level;
00167 setTopLevelMenuInternal( top_level );
00168 }
00169
00170 void KMenuBar::setTopLevelMenuInternal(bool top_level)
00171 {
00172 if (d->forcedTopLevel)
00173 top_level = true;
00174
00175 d->wasTopLevel = top_level;
00176 if( parentWidget()
00177 && parentWidget()->topLevelWidget()->isFullScreen())
00178 top_level = false;
00179
00180 if ( isTopLevelMenu() == top_level )
00181 return;
00182 d->topLevel = top_level;
00183 if ( isTopLevelMenu() )
00184 {
00185 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00186 d->selection = new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
00187 DefaultScreen( qt_xdisplay()));
00188 connect( d->selection, SIGNAL( newOwner( Window )),
00189 this, SLOT( updateFallbackSize()));
00190 connect( d->selection, SIGNAL( lostOwner()),
00191 this, SLOT( updateFallbackSize()));
00192 #endif
00193 d->frameStyle = frameStyle();
00194 d->lineWidth = lineWidth();
00195 d->margin = margin();
00196 d->fallback_mode = false;
00197 bool wasShown = !isHidden();
00198 reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder, QPoint(0,0), false );
00199 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00200 KWin::setType( winId(), NET::TopMenu );
00201 if( parentWidget())
00202 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00203 #endif
00204 QMenuBar::setFrameStyle( NoFrame );
00205 QMenuBar::setLineWidth( 0 );
00206 QMenuBar::setMargin( 0 );
00207 updateFallbackSize();
00208 d->min_size = QSize( 0, 0 );
00209 if( parentWidget() && !parentWidget()->isTopLevel())
00210 setShown( parentWidget()->isVisible());
00211 else if ( wasShown )
00212 show();
00213 } else
00214 {
00215 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00216 delete d->selection;
00217 d->selection = NULL;
00218 #endif
00219 setBackgroundMode( PaletteButton );
00220 setFrameStyle( d->frameStyle );
00221 setLineWidth( d->lineWidth );
00222 setMargin( d->margin );
00223 setMinimumSize( 0, 0 );
00224 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00225 menuContentsChanged();
00226 resize( sizeHint());
00227 if ( parentWidget() )
00228 reparent( parentWidget(), QPoint(0,0), !isHidden());
00229 }
00230 }
00231
00232 bool KMenuBar::isTopLevelMenu() const
00233 {
00234 return d->topLevel;
00235 }
00236
00237
00238 void KMenuBar::show()
00239 {
00240 QMenuBar::show();
00241 }
00242
00243 void KMenuBar::slotReadConfig()
00244 {
00245 KConfig *config = KGlobal::config();
00246 KConfigGroupSaver saver( config, "KDE" );
00247 setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
00248 }
00249
00250 bool KMenuBar::eventFilter(QObject *obj, QEvent *ev)
00251 {
00252 if ( d->topLevel )
00253 {
00254 if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
00255 {
00256 if( ev->type() == QEvent::Resize )
00257 return false;
00258 if ( ev->type() == QEvent::Accel || ev->type() == QEvent::AccelAvailable )
00259 {
00260 if ( QApplication::sendEvent( topLevelWidget(), ev ) )
00261 return true;
00262 }
00263 if(ev->type() == QEvent::ShowFullScreen )
00264
00265 setTopLevelMenuInternal( d->topLevel );
00266 }
00267 if( parentWidget() && obj == parentWidget() && ev->type() == QEvent::Reparent )
00268 {
00269 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00270 setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
00271 }
00272 if( parentWidget() && !parentWidget()->isTopLevel() && obj == parentWidget())
00273 {
00274 if( ev->type() == QEvent::Show )
00275 {
00276 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00277 show();
00278 }
00279 if( ev->type() == QEvent::Hide )
00280 hide();
00281 }
00282 }
00283 else
00284 {
00285 if( parentWidget() && obj == parentWidget()->topLevelWidget())
00286 {
00287 #if QT_VERSION >= 0x030300
00288 if( ev->type() == QEvent::WindowStateChange
00289 #else
00290 if( ( ev->type() == QEvent::ShowNormal || ev->type() == QEvent::ShowMaximized )
00291 #endif
00292 && !parentWidget()->topLevelWidget()->isFullScreen() )
00293 setTopLevelMenuInternal( d->wasTopLevel );
00294 }
00295 }
00296 return QMenuBar::eventFilter( obj, ev );
00297 }
00298
00299
00300 void KMenuBar::showEvent( QShowEvent *e )
00301 {
00302 QMenuBar::showEvent(e);
00303 }
00304
00305 void KMenuBar::updateFallbackSize()
00306 {
00307 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00308 if( !d->topLevel )
00309 return;
00310 if( d->selection->owner() != None )
00311 {
00312
00313 d->selection_timer.stop();
00314 if( d->fallback_mode )
00315 {
00316 d->fallback_mode = false;
00317
00318 #endif
00319 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00320 menuContentsChanged();
00321 resize( sizeHint());
00322 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00323 }
00324 return;
00325 }
00326 if( d->selection_timer.isActive())
00327 return;
00328 d->selection_timer.start( 100, true );
00329 #endif
00330 }
00331
00332 void KMenuBar::selectionTimeout()
00333 {
00334 if ( d->topLevel )
00335 {
00336 d->fallback_mode = true;
00337 KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama");
00338 int screen = xineramaConfig.readNumEntry("MenubarScreen",
00339 QApplication::desktop()->screenNumber(QPoint(0,0)) );
00340 QRect area = QApplication::desktop()->screenGeometry(screen);
00341 #if QT_VERSION < 0x030200
00342 int margin = frameWidth() + 2;
00343 #else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2
00344 int margin = 0;
00345 #endif
00346 move(area.left() - margin, area.top() - margin);
00347 setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
00348 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00349 int strut_height = height() - margin;
00350 if( strut_height < 0 )
00351 strut_height = 0;
00352 KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00353 #endif
00354 }
00355 }
00356
00357 int KMenuBar::block_resize = 0;
00358
00359 void KMenuBar::resizeEvent( QResizeEvent *e )
00360 {
00361 if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00362 {
00363 ++block_resize;
00364 QMenuBar::resizeEvent(e);
00365 --block_resize;
00366 }
00367 else
00368 QMenuBar::resizeEvent(e);
00369 }
00370
00371 void KMenuBar::setGeometry( const QRect& r )
00372 {
00373 setGeometry( r.x(), r.y(), r.width(), r.height() );
00374 }
00375
00376 void KMenuBar::setGeometry( int x, int y, int w, int h )
00377 {
00378 if( block_resize > 0 )
00379 {
00380 move( x, y );
00381 return;
00382 }
00383 checkSize( w, h );
00384 if( geometry() != QRect( x, y, w, h ))
00385 QMenuBar::setGeometry( x, y, w, h );
00386 }
00387
00388 void KMenuBar::resize( int w, int h )
00389 {
00390 if( block_resize > 0 )
00391 return;
00392 checkSize( w, h );
00393 if( size() != QSize( w, h ))
00394 QMenuBar::resize( w, h );
00395
00396 }
00397
00398 void KMenuBar::checkSize( int& w, int& h )
00399 {
00400 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00401 if( !d->topLevel || d->fallback_mode )
00402 return;
00403 #endif
00404 if( parentWidget() && parentWidget()->width() == w )
00405 {
00406
00407
00408
00409 ++block_resize;
00410 QSize s = sizeHint();
00411 w = s.width();
00412 h = s.height();
00413 --block_resize;
00414 }
00415
00416
00417
00418 w = KMAX( w, d->min_size.width());
00419 h = KMAX( h, d->min_size.height());
00420 }
00421
00422 bool KMenuBar::x11Event( XEvent* ev )
00423 {
00424 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00425 if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
00426 && ev->xclient.window == winId())
00427 {
00428
00429
00430
00431
00432 d->min_size = QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
00433
00434 menuContentsChanged();
00435 resize( sizeHint());
00436 return true;
00437 }
00438 #endif
00439 return QMenuBar::x11Event( ev );
00440 }
00441
00442 void KMenuBar::setFrameStyle( int style )
00443 {
00444 if( d->topLevel )
00445 d->frameStyle = style;
00446 else
00447 QMenuBar::setFrameStyle( style );
00448 }
00449
00450 void KMenuBar::setLineWidth( int width )
00451 {
00452 if( d->topLevel )
00453 d->lineWidth = width;
00454 else
00455 QMenuBar::setLineWidth( width );
00456 }
00457
00458 void KMenuBar::setMargin( int margin )
00459 {
00460 if( d->topLevel )
00461 d->margin = margin;
00462 else
00463 QMenuBar::setMargin( margin );
00464 }
00465
00466 void KMenuBar::closeEvent( QCloseEvent* e )
00467 {
00468 if( d->topLevel )
00469 e->ignore();
00470 else
00471 QMenuBar::closeEvent( e );
00472 }
00473
00474 void KMenuBar::drawContents( QPainter* p )
00475 {
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 if( !d->topLevel )
00488 {
00489 QMenuBar::drawContents(p);
00490 }
00491 else
00492 {
00493 bool up_enabled = isUpdatesEnabled();
00494 BackgroundMode bg_mode = backgroundMode();
00495 BackgroundOrigin bg_origin = backgroundOrigin();
00496
00497 setUpdatesEnabled(false);
00498 setBackgroundMode(X11ParentRelative);
00499 setBackgroundOrigin(WindowOrigin);
00500
00501 p->eraseRect( rect() );
00502 erase();
00503
00504 QColorGroup g = colorGroup();
00505 bool e;
00506
00507 for ( int i=0; i<(int)count(); i++ )
00508 {
00509 QMenuItem *mi = findItem( idAt( i ) );
00510
00511 if ( !mi->text().isNull() || mi->pixmap() )
00512 {
00513 QRect r = itemRect(i);
00514 if(r.isEmpty() || !mi->isVisible())
00515 continue;
00516
00517 e = mi->isEnabledAndVisible();
00518 if ( e )
00519 g = isEnabled() ? ( isActiveWindow() ? palette().active() :
00520 palette().inactive() ) : palette().disabled();
00521 else
00522 g = palette().disabled();
00523
00524 bool item_active = ( actItem == i );
00525
00526 p->setClipRect(r);
00527
00528 if( item_active )
00529 {
00530 QStyle::SFlags flags = QStyle::Style_Default;
00531 if (isEnabled() && e)
00532 flags |= QStyle::Style_Enabled;
00533 if ( item_active )
00534 flags |= QStyle::Style_Active;
00535 if ( item_active && actItemDown )
00536 flags |= QStyle::Style_Down;
00537 flags |= QStyle::Style_HasFocus;
00538
00539 style().drawControl(QStyle::CE_MenuBarItem, p, this,
00540 r, g, flags, QStyleOption(mi));
00541 }
00542 else
00543 {
00544 style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
00545 g, e, mi->pixmap(), mi->text());
00546 }
00547 }
00548 }
00549
00550 setBackgroundOrigin(bg_origin);
00551 setBackgroundMode(bg_mode);
00552 setUpdatesEnabled(up_enabled);
00553 }
00554 }
00555
00556 void KMenuBar::virtual_hook( int, void* )
00557 { }
00558
00559 #include "kmenubar.moc"