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 updateMenuBarSize();
00226 if ( parentWidget() )
00227 reparent( parentWidget(), QPoint(0,0), !isHidden());
00228 }
00229 }
00230
00231 bool KMenuBar::isTopLevelMenu() const
00232 {
00233 return d->topLevel;
00234 }
00235
00236
00237 void KMenuBar::show()
00238 {
00239 QMenuBar::show();
00240 }
00241
00242 void KMenuBar::slotReadConfig()
00243 {
00244 KConfig *config = KGlobal::config();
00245 KConfigGroupSaver saver( config, "KDE" );
00246 setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
00247 }
00248
00249 bool KMenuBar::eventFilter(QObject *obj, QEvent *ev)
00250 {
00251 if ( d->topLevel )
00252 {
00253 if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
00254 {
00255 if( ev->type() == QEvent::Resize )
00256 return false;
00257 if ( ev->type() == QEvent::Accel || ev->type() == QEvent::AccelAvailable )
00258 {
00259 if ( QApplication::sendEvent( topLevelWidget(), ev ) )
00260 return true;
00261 }
00262 if(ev->type() == QEvent::ShowFullScreen )
00263
00264 setTopLevelMenuInternal( d->topLevel );
00265 }
00266 if( parentWidget() && obj == parentWidget() && ev->type() == QEvent::Reparent )
00267 {
00268 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00269 setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
00270 }
00271 if( parentWidget() && !parentWidget()->isTopLevel() && obj == parentWidget())
00272 {
00273 if( ev->type() == QEvent::Show )
00274 {
00275 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00276 show();
00277 }
00278 if( ev->type() == QEvent::Hide )
00279 hide();
00280 }
00281 }
00282 else
00283 {
00284 if( parentWidget() && obj == parentWidget()->topLevelWidget())
00285 {
00286 #if QT_VERSION >= 0x030300
00287 if( ev->type() == QEvent::WindowStateChange
00288 #else
00289 if( ( ev->type() == QEvent::ShowNormal || ev->type() == QEvent::ShowMaximized )
00290 #endif
00291 && !parentWidget()->topLevelWidget()->isFullScreen() )
00292 setTopLevelMenuInternal( d->wasTopLevel );
00293 }
00294 }
00295 return QMenuBar::eventFilter( obj, ev );
00296 }
00297
00298
00299 void KMenuBar::showEvent( QShowEvent *e )
00300 {
00301 QMenuBar::showEvent(e);
00302 }
00303
00304 void KMenuBar::updateFallbackSize()
00305 {
00306 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00307 if( !d->topLevel )
00308 return;
00309 if( d->selection->owner() != None )
00310 {
00311
00312 d->selection_timer.stop();
00313 if( d->fallback_mode )
00314 {
00315 d->fallback_mode = false;
00316
00317 #endif
00318 setMinimumSize( 0, 0 );
00319 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00320 updateMenuBarSize();
00321 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00322 }
00323 return;
00324 }
00325 if( d->selection_timer.isActive())
00326 return;
00327 d->selection_timer.start( 100, true );
00328 #endif
00329 }
00330
00331 void KMenuBar::selectionTimeout()
00332 {
00333 if ( d->topLevel )
00334 {
00335 d->fallback_mode = true;
00336 KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama");
00337 int screen = xineramaConfig.readNumEntry("MenubarScreen",
00338 QApplication::desktop()->screenNumber(QPoint(0,0)) );
00339 QRect area = QApplication::desktop()->screenGeometry(screen);
00340 #if QT_VERSION < 0x030200
00341 int margin = frameWidth() + 2;
00342 #else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2
00343 int margin = 0;
00344 #endif
00345 move(area.left() - margin, area.top() - margin);
00346 setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
00347 #if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00348 int strut_height = height() - margin;
00349 if( strut_height < 0 )
00350 strut_height = 0;
00351 KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00352 #endif
00353 }
00354 }
00355
00356 int KMenuBar::block_resize = 0;
00357
00358 void KMenuBar::resizeEvent( QResizeEvent *e )
00359 {
00360 if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00361 {
00362 ++block_resize;
00363 QMenuBar::resizeEvent(e);
00364 --block_resize;
00365 }
00366 else
00367 QMenuBar::resizeEvent(e);
00368 }
00369
00370 void KMenuBar::setGeometry( const QRect& r )
00371 {
00372 setGeometry( r.x(), r.y(), r.width(), r.height() );
00373 }
00374
00375 void KMenuBar::setGeometry( int x, int y, int w, int h )
00376 {
00377 if( block_resize > 0 )
00378 {
00379 move( x, y );
00380 return;
00381 }
00382 checkSize( w, h );
00383 if( geometry() != QRect( x, y, w, h ))
00384 QMenuBar::setGeometry( x, y, w, h );
00385 }
00386
00387 void KMenuBar::resize( int w, int h )
00388 {
00389 if( block_resize > 0 )
00390 return;
00391 checkSize( w, h );
00392 if( size() != QSize( w, h ))
00393 QMenuBar::resize( w, h );
00394
00395 }
00396
00397 void KMenuBar::checkSize( int& w, int& h )
00398 {
00399 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00400 if( !d->topLevel || d->fallback_mode )
00401 return;
00402 #endif
00403 if( parentWidget() && parentWidget()->width() == w )
00404 {
00405
00406
00407
00408 ++block_resize;
00409 QSize s = sizeHint();
00410 w = s.width();
00411 h = s.height();
00412 --block_resize;
00413 }
00414
00415
00416
00417 w = KMAX( w, d->min_size.width());
00418 h = KMAX( h, d->min_size.height());
00419 }
00420
00421 bool KMenuBar::x11Event( XEvent* ev )
00422 {
00423 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
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 #endif
00437 return QMenuBar::x11Event( ev );
00438 }
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"