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 connect( qApp->desktop(), SIGNAL( resized(
int )), SLOT( updateKMenubarSize()));
00157 slotReadConfig();
00158 }
00159
00160 KMenuBar::~KMenuBar()
00161 {
00162
delete d;
00163 }
00164
00165 void KMenuBar::setTopLevelMenu(
bool top_level)
00166 {
00167 d->forcedTopLevel = top_level;
00168 setTopLevelMenuInternal( top_level );
00169 }
00170
00171
void KMenuBar::setTopLevelMenuInternal(
bool top_level)
00172 {
00173
if (d->forcedTopLevel)
00174 top_level =
true;
00175
00176 d->wasTopLevel = top_level;
00177
if( parentWidget()
00178 && parentWidget()->topLevelWidget()->isFullScreen())
00179 top_level =
false;
00180
00181
if (
isTopLevelMenu() == top_level )
00182
return;
00183 d->topLevel = top_level;
00184
if (
isTopLevelMenu() )
00185 {
00186
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00187
d->selection =
new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
00188 DefaultScreen( qt_xdisplay()));
00189 connect( d->selection, SIGNAL( newOwner( Window )),
00190
this, SLOT( updateFallbackSize()));
00191 connect( d->selection, SIGNAL( lostOwner()),
00192
this, SLOT( updateFallbackSize()));
00193
#endif
00194
d->frameStyle = frameStyle();
00195 d->lineWidth = lineWidth();
00196 d->margin = margin();
00197 d->fallback_mode =
false;
00198
bool wasShown = !isHidden();
00199 reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder,
QPoint(0,0),
false );
00200
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00201
KWin::setType( winId(), NET::TopMenu );
00202
if( parentWidget())
00203 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00204
#endif
00205
QMenuBar::setFrameStyle( NoFrame );
00206 QMenuBar::setLineWidth( 0 );
00207 QMenuBar::setMargin( 0 );
00208 updateFallbackSize();
00209 d->min_size =
QSize( 0, 0 );
00210
if( parentWidget() && !parentWidget()->isTopLevel())
00211 setShown( parentWidget()->isVisible());
00212
else if ( wasShown )
00213 show();
00214 }
else
00215 {
00216
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00217
delete d->selection;
00218 d->selection = NULL;
00219
#endif
00220
setBackgroundMode( PaletteButton );
00221 setFrameStyle( d->frameStyle );
00222 setLineWidth( d->lineWidth );
00223 setMargin( d->margin );
00224 setMinimumSize( 0, 0 );
00225 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00226 updateMenuBarSize();
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
setMinimumSize( 0, 0 );
00320 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00321 updateMenuBarSize();
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 updateMenuBarSize();
00435
return true;
00436 }
00437
#endif
00438
return QMenuBar::x11Event( ev );
00439 }
00440
00441
void KMenuBar::updateMenuBarSize()
00442 {
00443 menuContentsChanged();
00444 resize( sizeHint());
00445 }
00446
00447
void KMenuBar::setFrameStyle(
int style )
00448 {
00449
if( d->topLevel )
00450 d->frameStyle = style;
00451
else
00452 QMenuBar::setFrameStyle( style );
00453 }
00454
00455
void KMenuBar::setLineWidth(
int width )
00456 {
00457
if( d->topLevel )
00458 d->lineWidth = width;
00459
else
00460 QMenuBar::setLineWidth( width );
00461 }
00462
00463
void KMenuBar::setMargin(
int margin )
00464 {
00465
if( d->topLevel )
00466 d->margin = margin;
00467
else
00468 QMenuBar::setMargin( margin );
00469 }
00470
00471
void KMenuBar::closeEvent(
QCloseEvent* e )
00472 {
00473
if( d->topLevel )
00474 e->ignore();
00475
else
00476 QMenuBar::closeEvent( e );
00477 }
00478
00479
void KMenuBar::drawContents(
QPainter* p )
00480 {
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
if( !d->topLevel )
00493 {
00494 QMenuBar::drawContents(p);
00495 }
00496
else
00497 {
00498
bool up_enabled = isUpdatesEnabled();
00499 BackgroundMode bg_mode = backgroundMode();
00500 BackgroundOrigin bg_origin = backgroundOrigin();
00501
00502 setUpdatesEnabled(
false);
00503 setBackgroundMode(X11ParentRelative);
00504 setBackgroundOrigin(WindowOrigin);
00505
00506 p->eraseRect( rect() );
00507 erase();
00508
00509
QColorGroup g = colorGroup();
00510
bool e;
00511
00512
for (
int i=0; i<(
int)count(); i++ )
00513 {
00514 QMenuItem *mi = findItem( idAt( i ) );
00515
00516
if ( !mi->text().isNull() || mi->pixmap() )
00517 {
00518
QRect r = itemRect(i);
00519
if(r.isEmpty() || !mi->isVisible())
00520
continue;
00521
00522 e = mi->isEnabledAndVisible();
00523
if ( e )
00524 g = isEnabled() ? ( isActiveWindow() ? palette().active() :
00525 palette().inactive() ) : palette().disabled();
00526
else
00527 g = palette().disabled();
00528
00529
bool item_active = ( actItem == i );
00530
00531 p->setClipRect(r);
00532
00533
if( item_active )
00534 {
00535 QStyle::SFlags flags = QStyle::Style_Default;
00536
if (isEnabled() && e)
00537 flags |= QStyle::Style_Enabled;
00538
if ( item_active )
00539 flags |= QStyle::Style_Active;
00540
if ( item_active && actItemDown )
00541 flags |= QStyle::Style_Down;
00542 flags |= QStyle::Style_HasFocus;
00543
00544 style().drawControl(QStyle::CE_MenuBarItem, p,
this,
00545 r, g, flags,
QStyleOption(mi));
00546 }
00547
else
00548 {
00549 style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
00550 g, e, mi->pixmap(), mi->text());
00551 }
00552 }
00553 }
00554
00555 setBackgroundOrigin(bg_origin);
00556 setBackgroundMode(bg_mode);
00557 setUpdatesEnabled(up_enabled);
00558 }
00559 }
00560
00561
void KMenuBar::virtual_hook(
int,
void* )
00562 { }
00563
00564
#include "kmenubar.moc"