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
00033
#include <kconfig.h>
00034
#include <kglobalsettings.h>
00035
#include <kmenubar.h>
00036
#include <kapplication.h>
00037
00038
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00039
#include <kwin.h>
00040
#include <kwinmodule.h>
00041
#endif
00042
00043
#include <kglobal.h>
00044
#include <kdebug.h>
00045
00046
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00047
#include <qxembed.h>
00048
#endif
00049
00050
#include <kmanagerselection.h>
00051
#include <qtimer.h>
00052
00053
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00054
#include <X11/Xlib.h>
00055
#include <X11/Xutil.h>
00056
#include <X11/Xatom.h>
00057
#endif
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
class KMenuBar::KMenuBarPrivate
00073 {
00074
public:
00075 KMenuBarPrivate()
00076 : forcedTopLevel( false ),
00077 topLevel( false ),
00078 wasTopLevel( false ),
00079 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00080 selection( NULL ),
00081 #endif
00082 min_size( 0, 0 )
00083 {
00084 }
00085 ~KMenuBarPrivate()
00086 {
00087
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00088
delete selection;
00089
#endif
00090
}
00091
bool forcedTopLevel;
00092
bool topLevel;
00093
bool wasTopLevel;
00094
int frameStyle;
00095
int lineWidth;
00096
int margin;
00097
bool fallback_mode;
00098
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00099
KSelectionWatcher* selection;
00100
#endif
00101
QTimer selection_timer;
00102
QSize min_size;
00103
static Atom makeSelectionAtom();
00104 };
00105
00106
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00107
static Atom selection_atom = None;
00108
static Atom msg_type_atom = None;
00109
00110
static
00111
void initAtoms()
00112 {
00113
char nm[ 100 ];
00114 sprintf( nm,
"_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
00115
char nm2[] =
"_KDE_TOPMENU_MINSIZE";
00116
char* names[ 2 ] = { nm, nm2 };
00117 Atom atoms[ 2 ];
00118 XInternAtoms( qt_xdisplay(), names, 2, False, atoms );
00119 selection_atom = atoms[ 0 ];
00120 msg_type_atom = atoms[ 1 ];
00121 }
00122
#endif
00123
00124 Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom()
00125 {
00126
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00127
if( selection_atom == None )
00128 initAtoms();
00129
return selection_atom;
00130
#else
00131
return 0;
00132
#endif
00133
}
00134
00135 KMenuBar::KMenuBar(
QWidget *parent,
const char *name)
00136 :
QMenuBar(parent,
name)
00137 {
00138
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00139
QXEmbed::initialize();
00140
#endif
00141
d =
new KMenuBarPrivate;
00142 connect( &d->selection_timer, SIGNAL( timeout()),
00143
this, SLOT( selectionTimeout()));
00144
00145
#if (QT_VERSION-0 >= 0x030200) // XRANDR support
00146
connect( qApp->desktop(), SIGNAL( resized(
int )), SLOT( updateFallbackSize()));
00147
#endif
00148
00149
if ( kapp )
00150
00151 connect( kapp, SIGNAL(toolbarAppearanceChanged(
int)),
00152
this, SLOT(slotReadConfig()));
00153
00154 slotReadConfig();
00155 }
00156
00157 KMenuBar::~KMenuBar()
00158 {
00159
delete d;
00160 }
00161
00162 void KMenuBar::setTopLevelMenu(
bool top_level)
00163 {
00164 d->forcedTopLevel = top_level;
00165 setTopLevelMenuInternal( top_level );
00166 }
00167
00168
void KMenuBar::setTopLevelMenuInternal(
bool top_level)
00169 {
00170
if (d->forcedTopLevel)
00171 top_level =
true;
00172
00173 d->wasTopLevel = top_level;
00174
if( parentWidget()
00175 && parentWidget()->topLevelWidget()->isFullScreen())
00176 top_level =
false;
00177
00178
if (
isTopLevelMenu() == top_level )
00179
return;
00180 d->topLevel = top_level;
00181
if (
isTopLevelMenu() )
00182 {
00183
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00184
d->selection =
new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
00185 DefaultScreen( qt_xdisplay()));
00186 connect( d->selection, SIGNAL( newOwner( Window )),
00187
this, SLOT( updateFallbackSize()));
00188 connect( d->selection, SIGNAL( lostOwner()),
00189
this, SLOT( updateFallbackSize()));
00190
#endif
00191
d->frameStyle = frameStyle();
00192 d->lineWidth = lineWidth();
00193 d->margin = margin();
00194 d->fallback_mode =
false;
00195
bool wasShown = !isHidden();
00196 reparent( parentWidget(), WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder,
QPoint(0,0),
false );
00197
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00198
KWin::setType( winId(), NET::TopMenu );
00199
#endif
00200
QMenuBar::setFrameStyle( NoFrame );
00201 QMenuBar::setLineWidth( 0 );
00202 QMenuBar::setMargin( 0 );
00203 updateFallbackSize();
00204 d->min_size =
QSize( 0, 0 );
00205
if ( wasShown )
00206
show();
00207 }
else
00208 {
00209
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00210
delete d->selection;
00211 d->selection = NULL;
00212
#endif
00213
setBackgroundMode( PaletteButton );
00214 setFrameStyle( d->frameStyle );
00215 setLineWidth( d->lineWidth );
00216 setMargin( d->margin );
00217 setMinimumSize( 0, 0 );
00218 setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00219
menuContentsChanged();
00220 resize( sizeHint());
00221
if ( parentWidget() )
00222 reparent( parentWidget(),
QPoint(0,0), !isHidden());
00223 }
00224 }
00225
00226 bool KMenuBar::isTopLevelMenu()
const
00227
{
00228
return d->topLevel;
00229 }
00230
00231
00232
void KMenuBar::show()
00233 {
00234
QMenuBar::show();
00235 }
00236
00237
void KMenuBar::slotReadConfig()
00238 {
00239
KConfig *config =
KGlobal::config();
00240
KConfigGroupSaver saver( config,
"KDE" );
00241 setTopLevelMenuInternal( config->
readBoolEntry(
"macStyle",
false ) );
00242 }
00243
00244
bool KMenuBar::eventFilter(
QObject *obj,
QEvent *ev)
00245 {
00246
if ( d->topLevel )
00247 {
00248
if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
00249 {
00250
if( ev->
type() == QEvent::Resize )
00251
return false;
00252
if ( ev->
type() == QEvent::Accel || ev->
type() == QEvent::AccelAvailable )
00253 {
00254
if (
QApplication::sendEvent( topLevelWidget(), ev ) )
00255
return true;
00256 }
00257
if(ev->
type() == QEvent::ShowFullScreen )
00258
00259 setTopLevelMenuInternal( d->topLevel );
00260 }
00261 }
00262
else
00263 {
00264
if( parentWidget() && obj == parentWidget()->topLevelWidget())
00265 {
00266
#if QT_VERSION >= 0x030300
00267
if( ev->
type() == QEvent::WindowStateChange
00268
#else
00269
if( ( ev->
type() == QEvent::ShowNormal || ev->
type() == QEvent::ShowMaximized )
00270
#endif
00271
&& !parentWidget()->topLevelWidget()->isFullScreen() )
00272 setTopLevelMenuInternal( d->wasTopLevel );
00273 }
00274 }
00275
return QMenuBar::eventFilter( obj, ev );
00276 }
00277
00278
00279
void KMenuBar::showEvent(
QShowEvent *e )
00280 {
00281 QMenuBar::showEvent(e);
00282 }
00283
00284
void KMenuBar::updateFallbackSize()
00285 {
00286
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00287
if( !d->topLevel )
00288
return;
00289
if( d->selection->owner() != None )
00290 {
00291
00292 d->selection_timer.stop();
00293
if( d->fallback_mode )
00294 {
00295 d->fallback_mode =
false;
00296
00297
#endif
00298
setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00299
menuContentsChanged();
00300 resize( sizeHint());
00301
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00302
}
00303
return;
00304 }
00305
if( d->selection_timer.isActive())
00306
return;
00307 d->selection_timer.start( 100,
true );
00308
#endif
00309
}
00310
00311
void KMenuBar::selectionTimeout()
00312 {
00313
if ( d->topLevel )
00314 {
00315 d->fallback_mode =
true;
00316
KConfigGroup xineramaConfig(KGlobal::config(),
"Xinerama");
00317
int screen = xineramaConfig.readNumEntry(
"MenubarScreen",
00318 QApplication::desktop()->screenNumber(
QPoint(0,0)) );
00319
QRect area =
QApplication::desktop()->screenGeometry(screen);
00320
#if QT_VERSION < 0x030200
00321
int margin = frameWidth() + 2;
00322
#else // hopefully I'll manage to persuade TT on Fitts' Law for QMenuBar for Qt-3.2
00323
int margin = 0;
00324
#endif
00325
move(area.
left() - margin, area.
top() - margin);
00326 setFixedSize(area.
width() + 2* margin ,
heightForWidth( area.
width() + 2 * margin ) );
00327
#if defined Q_WS_X11 && ! defined K_WS_QTONLY //FIXME
00328
int strut_height = height() - margin;
00329
if( strut_height < 0 )
00330 strut_height = 0;
00331
KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00332
#endif
00333
}
00334 }
00335
00336
int KMenuBar::block_resize = 0;
00337
00338
void KMenuBar::resizeEvent(
QResizeEvent *e )
00339 {
00340
if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00341 {
00342 ++block_resize;
00343 QMenuBar::resizeEvent(e);
00344 --block_resize;
00345 }
00346
else
00347 QMenuBar::resizeEvent(e);
00348 }
00349
00350
void KMenuBar::setGeometry(
const QRect& r )
00351 {
00352 setGeometry( r.
x(), r.
y(), r.
width(), r.
height() );
00353 }
00354
00355
void KMenuBar::setGeometry(
int x,
int y,
int w,
int h )
00356 {
00357
if( block_resize > 0 )
00358 {
00359
move( x, y );
00360
return;
00361 }
00362 checkSize( w, h );
00363
if( geometry() !=
QRect( x, y, w, h ))
00364 QMenuBar::setGeometry( x, y, w, h );
00365 }
00366
00367
void KMenuBar::resize(
int w,
int h )
00368 {
00369
if( block_resize > 0 )
00370
return;
00371 checkSize( w, h );
00372
if( size() !=
QSize( w, h ))
00373 QMenuBar::resize( w, h );
00374
00375 }
00376
00377
void KMenuBar::checkSize(
int& w,
int& h )
00378 {
00379
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00380
if( !d->topLevel || d->fallback_mode )
00381
return;
00382
#endif
00383
if( parentWidget() && parentWidget()->width() == w )
00384 {
00385
00386
00387
00388 ++block_resize;
00389
QSize s = sizeHint();
00390 w = s.
width();
00391 h = s.
height();
00392 --block_resize;
00393 }
00394
00395
00396
00397 w =
KMAX( w, d->min_size.width());
00398 h =
KMAX( h, d->min_size.height());
00399 }
00400
00401
bool KMenuBar::x11Event( XEvent* ev )
00402 {
00403
#if defined Q_WS_X11 && ! defined K_WS_QTONLY
00404
if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
00405 && ev->xclient.window == winId())
00406 {
00407
00408
00409
00410
00411 d->min_size =
QSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
00412
00413
menuContentsChanged();
00414 resize( sizeHint());
00415
return true;
00416 }
00417
#endif
00418
return QMenuBar::x11Event( ev );
00419 }
00420
00421
void KMenuBar::setFrameStyle(
int style )
00422 {
00423
if( d->topLevel )
00424 d->frameStyle = style;
00425
else
00426 QMenuBar::setFrameStyle( style );
00427 }
00428
00429
void KMenuBar::setLineWidth(
int width )
00430 {
00431
if( d->topLevel )
00432 d->lineWidth = width;
00433
else
00434 QMenuBar::setLineWidth( width );
00435 }
00436
00437
void KMenuBar::setMargin(
int margin )
00438 {
00439
if( d->topLevel )
00440 d->margin = margin;
00441
else
00442 QMenuBar::setMargin( margin );
00443 }
00444
00445
void KMenuBar::closeEvent(
QCloseEvent* e )
00446 {
00447
if( d->topLevel )
00448 e->
ignore();
00449
else
00450 QMenuBar::closeEvent( e );
00451 }
00452
00453
void KMenuBar::virtual_hook(
int,
void* )
00454 { }
00455
00456
#include "kmenubar.moc"