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
#if (QT_VERSION-0 >= 0x030200) // XRANDR support
00140
connect( qApp->desktop(), SIGNAL( resized(
int )), SLOT( updateFallbackSize()));
00141
#endif
00142
00143
if ( kapp )
00144
00145 connect( kapp, SIGNAL(toolbarAppearanceChanged(
int)),
00146
this, SLOT(slotReadConfig()));
00147
00148 slotReadConfig();
00149 }
00150
00151 KMenuBar::~KMenuBar()
00152 {
00153
delete d;
00154 }
00155
00156 void KMenuBar::setTopLevelMenu(
bool top_level)
00157 {
00158 d->forcedTopLevel = top_level;
00159 setTopLevelMenuInternal( top_level );
00160 }
00161
00162
void KMenuBar::setTopLevelMenuInternal(
bool top_level)
00163 {
00164
if (d->forcedTopLevel)
00165 top_level =
true;
00166
00167 d->wasTopLevel = top_level;
00168
if( parentWidget()
00169 && parentWidget()->topLevelWidget()->isFullScreen())
00170 top_level =
false;
00171
00172
if (
isTopLevelMenu() == top_level )
00173
return;
00174 d->topLevel = top_level;
00175
if (
isTopLevelMenu() )
00176 {
00177
#ifdef Q_WS_X11
00178
d->selection =
new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
00179 DefaultScreen( qt_xdisplay()));
00180 connect( d->selection, SIGNAL( newOwner( Window )),
00181
this, SLOT( updateFallbackSize()));
00182 connect( d->selection, SIGNAL( lostOwner()),
00183
this, SLOT( updateFallbackSize()));
00184
#endif
00185
d->frameStyle = frameStyle();
00186 d->lineWidth = lineWidth();
00187 d->margin = margin();
00188 d->fallback_mode =
false;
00189
bool wasShown = !isHidden();
00190 reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder,
QPoint(0,0),
false );
00191
#ifdef Q_WS_X11
00192
KWin::setType( winId(), NET::TopMenu );
00193
if( parentWidget())
00194 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00195
#endif
00196
QMenuBar::setFrameStyle( NoFrame );
00197 QMenuBar::setLineWidth( 0 );
00198 QMenuBar::setMargin( 0 );
00199 updateFallbackSize();
00200 d->min_size =
QSize( 0, 0 );
00201
if( parentWidget() && !parentWidget()->isTopLevel())
00202 setShown( parentWidget()->isVisible());
00203
else if ( wasShown )
00204
show();
00205 }
else
00206 {
00207
#ifdef Q_WS_X11
00208
delete d->selection;
00209 d->selection = NULL;
00210
#endif
00211
setBackgroundMode( PaletteButton );
00212 setFrameStyle( d->frameStyle );
00213 setLineWidth( d->lineWidth );
00214 setMargin( d->margin );
00215 setMinimumSize( 0, 0 );
00216 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00217 updateMenuBarSize();
00218
if ( parentWidget() )
00219 reparent( parentWidget(),
QPoint(0,0), !isHidden());
00220 }
00221 }
00222
00223 bool KMenuBar::isTopLevelMenu()
const
00224
{
00225
return d->topLevel;
00226 }
00227
00228
00229
void KMenuBar::show()
00230 {
00231
QMenuBar::show();
00232 }
00233
00234
void KMenuBar::slotReadConfig()
00235 {
00236
KConfig *config =
KGlobal::config();
00237
KConfigGroupSaver saver( config,
"KDE" );
00238 setTopLevelMenuInternal( config->
readBoolEntry(
"macStyle",
false ) );
00239 }
00240
00241
bool KMenuBar::eventFilter(
QObject *obj,
QEvent *ev)
00242 {
00243
if ( d->topLevel )
00244 {
00245
if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
00246 {
00247
if( ev->
type() == QEvent::Resize )
00248
return false;
00249
if ( ev->
type() == QEvent::Accel || ev->
type() == QEvent::AccelAvailable )
00250 {
00251
if (
QApplication::sendEvent( topLevelWidget(), ev ) )
00252
return true;
00253 }
00254
if(ev->
type() == QEvent::ShowFullScreen )
00255
00256 setTopLevelMenuInternal( d->topLevel );
00257 }
00258
if( parentWidget() && obj == parentWidget() && ev->
type() == QEvent::Reparent )
00259 {
00260
#ifdef Q_WS_X11
00261
XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00262
#else
00263
00264
#endif
00265
setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
00266 }
00267
if( parentWidget() && !parentWidget()->isTopLevel() && obj == parentWidget())
00268 {
00269
if( ev->
type() == QEvent::Show )
00270 {
00271
#ifdef Q_WS_X11
00272
XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00273
#else
00274
00275
#endif
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( !d->topLevel )
00307
return;
00308
#ifdef Q_WS_X11
00309
if( d->selection->owner() != None )
00310
#endif
00311
{
00312
00313 d->selection_timer.stop();
00314
if( d->fallback_mode )
00315 {
00316 d->fallback_mode =
false;
00317
00318 setMinimumSize( 0, 0 );
00319 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00320 updateMenuBarSize();
00321 }
00322
return;
00323 }
00324
if( d->selection_timer.isActive())
00325
return;
00326 d->selection_timer.start( 100,
true );
00327 }
00328
00329
void KMenuBar::selectionTimeout()
00330 {
00331
if ( d->topLevel )
00332 {
00333 d->fallback_mode =
true;
00334
KConfigGroup xineramaConfig(KGlobal::config(),
"Xinerama");
00335
int screen = xineramaConfig.
readNumEntry(
"MenubarScreen",
00336 QApplication::desktop()->screenNumber(
QPoint(0,0)) );
00337
QRect area =
QApplication::desktop()->screenGeometry(screen);
00338
#if QT_VERSION < 0x030200
00339
int margin = frameWidth() + 2;
00340
#else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2
00341
int margin = 0;
00342
#endif
00343
move(area.
left() - margin, area.
top() - margin);
00344 setFixedSize(area.
width() + 2* margin ,
heightForWidth( area.
width() + 2 * margin ) );
00345
#ifdef Q_WS_X11
00346
int strut_height = height() - margin;
00347
if( strut_height < 0 )
00348 strut_height = 0;
00349 KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00350
#endif
00351
}
00352 }
00353
00354
int KMenuBar::block_resize = 0;
00355
00356
void KMenuBar::resizeEvent(
QResizeEvent *e )
00357 {
00358
if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00359 {
00360 ++block_resize;
00361 QMenuBar::resizeEvent(e);
00362 --block_resize;
00363 }
00364
else
00365 QMenuBar::resizeEvent(e);
00366 }
00367
00368
void KMenuBar::setGeometry(
const QRect& r )
00369 {
00370 setGeometry( r.
x(), r.
y(), r.
width(), r.
height() );
00371 }
00372
00373
void KMenuBar::setGeometry(
int x,
int y,
int w,
int h )
00374 {
00375
if( block_resize > 0 )
00376 {
00377
move( x, y );
00378
return;
00379 }
00380 checkSize( w, h );
00381
if( geometry() !=
QRect( x, y, w, h ))
00382 QMenuBar::setGeometry( x, y, w, h );
00383 }
00384
00385
void KMenuBar::resize(
int w,
int h )
00386 {
00387
if( block_resize > 0 )
00388
return;
00389 checkSize( w, h );
00390
if( size() !=
QSize( w, h ))
00391 QMenuBar::resize( w, h );
00392
00393 }
00394
00395
void KMenuBar::checkSize(
int& w,
int& h )
00396 {
00397
if( !d->topLevel || d->fallback_mode )
00398
return;
00399
QSize s = sizeHint();
00400 w = s.
width();
00401 h = s.
height();
00402
00403
00404
00405 w =
KMAX( w, d->min_size.width());
00406 h =
KMAX( h, d->min_size.height());
00407 }
00408
00409
00410
QSize KMenuBar::sizeHint()
const
00411
{
00412
if( !d->topLevel || block_resize > 0 )
00413
return QMenuBar::sizeHint();
00414
00415
00416 ++block_resize;
00417
00418
int h =
heightForWidth( 1000000 );
00419
int w = QMenuBar::sizeHint().width();
00420
00421
while( heightForWidth( w + 12 ) > h )
00422 w += 12;
00423
while( heightForWidth( w + 4 ) > h )
00424 w += 4;
00425
while( heightForWidth( w ) > h )
00426 ++w;
00427 --block_resize;
00428
return QSize( w, h );
00429 }
00430
00431
#ifdef Q_WS_X11
00432
bool KMenuBar::x11Event( XEvent* ev )
00433 {
00434
if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
00435 && ev->xclient.window == winId())
00436 {
00437
00438
00439
00440
00441 d->min_size =
QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
00442
00443 updateMenuBarSize();
00444
return true;
00445 }
00446
return QMenuBar::x11Event( ev );
00447 }
00448
#endif
00449
00450
void KMenuBar::updateMenuBarSize()
00451 {
00452
menuContentsChanged();
00453 resize( sizeHint());
00454 }
00455
00456
void KMenuBar::setFrameStyle(
int style )
00457 {
00458
if( d->topLevel )
00459 d->frameStyle = style;
00460
else
00461 QMenuBar::setFrameStyle( style );
00462 }
00463
00464
void KMenuBar::setLineWidth(
int width )
00465 {
00466
if( d->topLevel )
00467 d->lineWidth = width;
00468
else
00469 QMenuBar::setLineWidth( width );
00470 }
00471
00472
void KMenuBar::setMargin(
int margin )
00473 {
00474
if( d->topLevel )
00475 d->margin = margin;
00476
else
00477 QMenuBar::setMargin( margin );
00478 }
00479
00480
void KMenuBar::closeEvent(
QCloseEvent* e )
00481 {
00482
if( d->topLevel )
00483 e->
ignore();
00484
else
00485 QMenuBar::closeEvent( e );
00486 }
00487
00488
void KMenuBar::drawContents(
QPainter* p )
00489 {
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
if( !d->topLevel )
00502 {
00503
QMenuBar::drawContents(p);
00504 }
00505
else
00506 {
00507
bool up_enabled = isUpdatesEnabled();
00508 BackgroundMode bg_mode = backgroundMode();
00509 BackgroundOrigin bg_origin = backgroundOrigin();
00510
00511 setUpdatesEnabled(
false);
00512 setBackgroundMode(X11ParentRelative);
00513 setBackgroundOrigin(WindowOrigin);
00514
00515 p->
eraseRect( rect() );
00516 erase();
00517
00518
QColorGroup g = colorGroup();
00519
bool e;
00520
00521
for (
int i=0; i<(
int)count(); i++ )
00522 {
00523 QMenuItem *mi = findItem( idAt( i ) );
00524
00525
if ( !mi->text().isNull() || mi->pixmap() )
00526 {
00527
QRect r = itemRect(i);
00528
if(r.
isEmpty() || !mi->isVisible())
00529
continue;
00530
00531 e = mi->isEnabledAndVisible();
00532
if ( e )
00533 g = isEnabled() ? ( isActiveWindow() ? palette().active() :
00534 palette().inactive() ) : palette().disabled();
00535
else
00536 g = palette().disabled();
00537
00538
bool item_active = ( actItem == i );
00539
00540 p->
setClipRect(r);
00541
00542
if( item_active )
00543 {
00544 QStyle::SFlags flags = QStyle::Style_Default;
00545
if (isEnabled() && e)
00546 flags |= QStyle::Style_Enabled;
00547
if ( item_active )
00548 flags |= QStyle::Style_Active;
00549
if ( item_active && actItemDown )
00550 flags |= QStyle::Style_Down;
00551 flags |= QStyle::Style_HasFocus;
00552
00553 style().drawControl(QStyle::CE_MenuBarItem, p,
this,
00554 r, g, flags,
QStyleOption(mi));
00555 }
00556
else
00557 {
00558 style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
00559 g, e, mi->pixmap(), mi->text());
00560 }
00561 }
00562 }
00563
00564 setBackgroundOrigin(bg_origin);
00565 setBackgroundMode(bg_mode);
00566 setUpdatesEnabled(up_enabled);
00567 }
00568 }
00569
00570
void KMenuBar::virtual_hook(
int,
void* )
00571 { }
00572
00573
#include "kmenubar.moc"