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