• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kdeui
 

kdeui

kmenubar.cpp
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 1997, 1998, 1999, 2000  Sven Radej (radej@kde.org)
00003     Copyright (C) 1997, 1998, 1999, 2000 Matthias Ettrich (ettrich@kde.org)
00004     Copyright (C) 1999, 2000 Daniel "Mosfet" Duley (mosfet@kde.org)
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020     */
00021 
00022 
00023 #ifndef INCLUDE_MENUITEM_DEF
00024 #define INCLUDE_MENUITEM_DEF
00025 #endif
00026 
00027 #include "config.h"
00028 #include <tqevent.h>
00029 #include <tqobjectlist.h>
00030 #include <tqaccel.h>
00031 #include <tqpainter.h>
00032 #include <tqstyle.h>
00033 #include <tqtimer.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 
00052 #ifndef None
00053 #define None 0L
00054 #endif
00055 #endif
00056 
00057 /*
00058 
00059  Toplevel menubar (not for the fallback size handling done by itself):
00060  - should not alter position or set strut
00061  - every toplevel must have at most one matching topmenu
00062  - embedder won't allow shrinking below a certain size
00063  - must have WM_TRANSIENT_FOR pointing the its mainwindow
00064      - the exception is desktop's menubar, which can be transient for root window
00065        because of using root window as the desktop window
00066  - Fitts' Law
00067 
00068 */
00069 
00070 class KMenuBar::KMenuBarPrivate
00071 {
00072 public:
00073     KMenuBarPrivate()
00074     :   forcedTopLevel( false ),
00075         topLevel( false ),
00076         wasTopLevel( false ),
00077 #ifdef Q_WS_X11
00078         selection( NULL ),
00079 #endif
00080             min_size( 0, 0 )
00081     {
00082     }
00083     ~KMenuBarPrivate()
00084         {
00085 #ifdef Q_WS_X11
00086         delete selection;
00087 #endif
00088         }
00089     bool forcedTopLevel;
00090     bool topLevel;
00091     bool wasTopLevel; // when TLW is fullscreen, remember state
00092     int frameStyle; // only valid in toplevel mode
00093     int lineWidth;  // dtto
00094     int margin;     // dtto
00095     bool fallback_mode; // dtto
00096 #ifdef Q_WS_X11
00097     KSelectionWatcher* selection;
00098 #endif
00099     TQTimer selection_timer;
00100     TQSize min_size;
00101     static Atom makeSelectionAtom();
00102 };
00103 
00104 #ifdef Q_WS_X11
00105 static Atom selection_atom = None;
00106 static Atom msg_type_atom = None;
00107 
00108 static
00109 void initAtoms()
00110 {
00111     char nm[ 100 ];
00112     sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( qt_xdisplay()));
00113     char nm2[] = "_KDE_TOPMENU_MINSIZE";
00114     char* names[ 2 ] = { nm, nm2 };
00115     Atom atoms[ 2 ];
00116     XInternAtoms( qt_xdisplay(), names, 2, False, atoms );
00117     selection_atom = atoms[ 0 ];
00118     msg_type_atom = atoms[ 1 ];
00119 }
00120 #endif
00121 
00122 Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom()
00123 {
00124 #ifdef Q_WS_X11
00125     if( selection_atom == None )
00126     initAtoms();
00127     return selection_atom;
00128 #else
00129     return 0;
00130 #endif
00131 }
00132 
00133 KMenuBar::KMenuBar(TQWidget *parent, const char *name)
00134   : TQMenuBar(parent, name)
00135 {
00136 #ifdef Q_WS_X11
00137     QXEmbed::initialize();
00138 #endif
00139     d = new KMenuBarPrivate;
00140     connect( &d->selection_timer, TQT_SIGNAL( timeout()),
00141         this, TQT_SLOT( selectionTimeout()));
00142 
00143     connect( tqApp->desktop(), TQT_SIGNAL( resized( int )), TQT_SLOT( updateFallbackSize()));
00144 
00145     if ( kapp )
00146         // toolbarAppearanceChanged(int) is sent when changing macstyle
00147         connect( kapp, TQT_SIGNAL(toolbarAppearanceChanged(int)),
00148             this, TQT_SLOT(slotReadConfig()));
00149 
00150     slotReadConfig();
00151 }
00152 
00153 KMenuBar::~KMenuBar()
00154 {
00155   delete d;
00156 }
00157 
00158 void KMenuBar::setTopLevelMenu(bool top_level)
00159 {
00160   d->forcedTopLevel = top_level;
00161   setTopLevelMenuInternal( top_level );
00162 }
00163 
00164 void KMenuBar::setTopLevelMenuInternal(bool top_level)
00165 {
00166   if (d->forcedTopLevel)
00167     top_level = true;
00168 
00169   d->wasTopLevel = top_level;
00170   if( parentWidget()
00171       && parentWidget()->topLevelWidget()->isFullScreen())
00172     top_level = false;
00173 
00174   if ( isTopLevelMenu() == top_level )
00175     return;
00176   d->topLevel = top_level;
00177   if ( isTopLevelMenu() )
00178   {
00179 #ifdef Q_WS_X11
00180       d->selection = new KSelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
00181           DefaultScreen( qt_xdisplay()));
00182       connect( d->selection, TQT_SIGNAL( newOwner( Window )),
00183           this, TQT_SLOT( updateFallbackSize()));
00184       connect( d->selection, TQT_SIGNAL( lostOwner()),
00185           this, TQT_SLOT( updateFallbackSize()));
00186 #endif
00187       d->frameStyle = frameStyle();
00188       d->lineWidth = lineWidth();
00189       d->margin = margin();
00190       d->fallback_mode = false;
00191       bool wasShown = !isHidden();
00192       reparent( parentWidget(), (WFlags)(WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder), TQPoint(0,0), false );
00193 #ifdef Q_WS_X11
00194       KWin::setType( winId(), NET::TopMenu );
00195       if( parentWidget())
00196           XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00197 #endif
00198       TQMenuBar::setFrameStyle( NoFrame );
00199       TQMenuBar::setLineWidth( 0 );
00200       TQMenuBar::setMargin( 0 );
00201       updateFallbackSize();
00202       d->min_size = TQSize( 0, 0 );
00203       if( parentWidget() && !parentWidget()->isTopLevel())
00204           setShown( parentWidget()->isVisible());
00205       else if ( wasShown )
00206           show();
00207   } else
00208   {
00209 #ifdef Q_WS_X11
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       updateMenuBarSize();
00220       if ( parentWidget() )
00221           reparent( parentWidget(), TQPoint(0,0), !isHidden());
00222   }
00223 }
00224 
00225 bool KMenuBar::isTopLevelMenu() const
00226 {
00227   return d->topLevel;
00228 }
00229 
00230 // KDE4 remove
00231 void KMenuBar::show()
00232 {
00233     TQMenuBar::show();
00234 }
00235 
00236 void KMenuBar::slotReadConfig()
00237 {
00238   KConfig *config = KGlobal::config();
00239   KConfigGroupSaver saver( config, "KDE" );
00240   setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
00241 }
00242 
00243 bool KMenuBar::eventFilter(TQObject *obj, TQEvent *ev)
00244 {
00245     if ( d->topLevel )
00246     {
00247     if ( parentWidget() && TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(parentWidget()->topLevelWidget())  )
00248         {
00249         if( ev->type() == TQEvent::Resize )
00250         return false; // ignore resizing of parent, TQMenuBar would try to adjust size
00251         if ( ev->type() == TQEvent::Accel || ev->type() == TQEvent::AccelAvailable )
00252             {
00253         if ( TQApplication::sendEvent( topLevelWidget(), ev ) )
00254             return true;
00255         }
00256             if(ev->type() == TQEvent::ShowFullScreen )
00257                 // will update the state properly
00258                 setTopLevelMenuInternal( d->topLevel );
00259         }
00260         if( parentWidget() && TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(parentWidget()) && ev->type() == TQEvent::Reparent )
00261             {
00262 #ifdef Q_WS_X11
00263             XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00264 #else
00265             //TODO: WIN32?
00266 #endif
00267             setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
00268             }
00269         if( parentWidget() && !parentWidget()->isTopLevel() && TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(parentWidget()))
00270         { // if the parent is not toplevel, KMenuBar needs to match its visibility status
00271             if( ev->type() == TQEvent::Show )
00272                 {
00273 #ifdef Q_WS_X11
00274                 XSetTransientForHint( qt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
00275 #else
00276                 //TODO: WIN32?
00277 #endif
00278                 show();
00279                 }
00280             if( ev->type() == TQEvent::Hide )
00281                 hide();
00282     }
00283     }
00284     else
00285     {
00286         if( parentWidget() && TQT_BASE_OBJECT(obj) == TQT_BASE_OBJECT(parentWidget()->topLevelWidget()))
00287         {
00288             if( ev->type() == TQEvent::WindowStateChange
00289                 && !parentWidget()->topLevelWidget()->isFullScreen() )
00290                 setTopLevelMenuInternal( d->wasTopLevel );
00291         }
00292     }
00293     return TQMenuBar::eventFilter( obj, ev );
00294 }
00295 
00296 // KDE4 remove
00297 void KMenuBar::showEvent( TQShowEvent *e )
00298 {
00299     TQMenuBar::showEvent(e);
00300 }
00301 
00302 void KMenuBar::updateFallbackSize()
00303 {
00304     if( !d->topLevel )
00305     return;
00306 #ifdef Q_WS_X11
00307     if( d->selection->owner() != None )
00308 #endif
00309     { // somebody is managing us, don't mess anything, undo changes
00310       // done in fallback mode if needed
00311         d->selection_timer.stop();
00312         if( d->fallback_mode )
00313         {
00314             d->fallback_mode = false;
00315             KWin::setStrut( winId(), 0, 0, 0, 0 );
00316             setMinimumSize( 0, 0 );
00317             setMaximumSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX );
00318             updateMenuBarSize();
00319         }
00320     return;
00321     }
00322     if( d->selection_timer.isActive())
00323     return;
00324     d->selection_timer.start( 100, true );
00325 }
00326 
00327 void KMenuBar::selectionTimeout()
00328 { // nobody is managing us, handle resizing
00329     if ( d->topLevel )
00330     {
00331         d->fallback_mode = true; // KMenuBar is handling its position itself
00332         KConfigGroup xineramaConfig(KGlobal::config(),"Xinerama");
00333         int screen = xineramaConfig.readNumEntry("MenubarScreen",
00334             TQApplication::desktop()->screenNumber(TQPoint(0,0)) );
00335         TQRect area;
00336         if (kapp->desktop()->numScreens() < 2)
00337             area = kapp->desktop()->geometry();
00338         else
00339             area = kapp->desktop()->screenGeometry(screen);
00340         int margin = 0;
00341     move(area.left() - margin, area.top() - margin); 
00342         setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
00343 #ifdef Q_WS_X11
00344         int strut_height = height() - margin;
00345         if( strut_height < 0 )
00346             strut_height = 0;
00347         KWin::setStrut( winId(), 0, 0, strut_height, 0 );
00348 #endif
00349     }
00350 }
00351 
00352 int KMenuBar::block_resize = 0;
00353 
00354 void KMenuBar::resizeEvent( TQResizeEvent *e )
00355 {
00356     if( e->spontaneous() && d->topLevel && !d->fallback_mode )
00357         {
00358         ++block_resize; // do not respond with configure request to ConfigureNotify event
00359         TQMenuBar::resizeEvent(e); // to avoid possible infinite loop
00360         --block_resize;
00361         }
00362     else
00363         TQMenuBar::resizeEvent(e);
00364 }
00365 
00366 void KMenuBar::setGeometry( const TQRect& r )
00367 {
00368     setGeometry( r.x(), r.y(), r.width(), r.height() );
00369 }
00370 
00371 void KMenuBar::setGeometry( int x, int y, int w, int h )
00372 {
00373     if( block_resize > 0 )
00374     {
00375     move( x, y );
00376     return;
00377     }
00378     checkSize( w, h );
00379     if( geometry() != TQRect( x, y, w, h ))
00380         TQMenuBar::setGeometry( x, y, w, h );
00381 }
00382 
00383 void KMenuBar::resize( int w, int h )
00384 {
00385     if( block_resize > 0 )
00386     return;
00387     checkSize( w, h );
00388     if( size() != TQSize( w, h ))
00389         TQMenuBar::resize( w, h );
00390 //    kdDebug() << "RS:" << w << ":" << h << ":" << width() << ":" << height() << ":" << minimumWidth() << ":" << minimumHeight() << endl;
00391 }
00392 
00393 void KMenuBar::checkSize( int& w, int& h )
00394 {
00395     if( !d->topLevel || d->fallback_mode )
00396     return;
00397     TQSize s = sizeHint();
00398     w = s.width();
00399     h = s.height();
00400     // This is not done as setMinimumSize(), because that would set the minimum
00401     // size in WM_NORMAL_HINTS, and KWin would not allow changing to smaller size
00402     // anymore
00403     w = KMAX( w, d->min_size.width());
00404     h = KMAX( h, d->min_size.height());
00405 }
00406 
00407 // QMenuBar's sizeHint() gives wrong size (insufficient width), which causes wrapping in the kicker applet
00408 TQSize KMenuBar::sizeHint() const
00409 {
00410     if( !d->topLevel || block_resize > 0 )
00411         return TQMenuBar::sizeHint();
00412     // Since TQMenuBar::sizeHint() may indirectly call resize(),
00413     // avoid infinite recursion.
00414     ++block_resize;
00415     // find the minimum useful height, and enlarge the width until the menu fits in that height (one row)
00416     int h = heightForWidth( 1000000 );
00417     int w = TQMenuBar::sizeHint().width();
00418     // optimization - don't call heightForWidth() too many times
00419     while( heightForWidth( w + 12 ) > h )
00420         w += 12;
00421     while( heightForWidth( w + 4 ) > h )
00422         w += 4;
00423     while( heightForWidth( w ) > h )
00424         ++w;
00425     --block_resize;
00426     return TQSize( w, h );
00427 }
00428 
00429 #ifdef Q_WS_X11
00430 bool KMenuBar::x11Event( XEvent* ev )
00431 {
00432     if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
00433         && ev->xclient.window == winId())
00434     {
00435         // TQMenuBar is trying really hard to keep the size it deems right.
00436         // Forcing minimum size and blocking resizing to match parent size
00437         // in checkResizingToParent() seem to be the only way to make
00438         // KMenuBar keep the size it wants
00439     d->min_size = TQSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
00440 //        kdDebug() << "MINSIZE:" << d->min_size << endl;
00441         updateMenuBarSize();
00442     return true;
00443     }
00444     return TQMenuBar::x11Event( ev );
00445 }
00446 #endif
00447 
00448 void KMenuBar::updateMenuBarSize()
00449     {
00450     menuContentsChanged(); // trigger invalidating calculated size
00451     resize( sizeHint());   // and resize to preferred size
00452     }
00453 
00454 void KMenuBar::setFrameStyle( int style )
00455 {
00456     if( d->topLevel )
00457     d->frameStyle = style;
00458     else
00459     TQMenuBar::setFrameStyle( style );
00460 }
00461 
00462 void KMenuBar::setLineWidth( int width )
00463 {
00464     if( d->topLevel )
00465     d->lineWidth = width;
00466     else
00467     TQMenuBar::setLineWidth( width );
00468 }
00469 
00470 void KMenuBar::setMargin( int margin )
00471 {
00472     if( d->topLevel )
00473     d->margin = margin;
00474     else
00475     TQMenuBar::setMargin( margin );
00476 }
00477 
00478 void KMenuBar::closeEvent( TQCloseEvent* e )
00479 {
00480     if( d->topLevel )
00481         e->ignore(); // mainly for the fallback mode 
00482     else
00483         TQMenuBar::closeEvent( e );
00484 }
00485 
00486 void KMenuBar::drawContents( TQPainter* p )
00487 {
00488     // Closes the BR77113
00489     // We need to overload this method to paint only the menu items
00490     // This way when the KMenuBar is embedded in the menu applet it
00491     // integrates correctly.
00492     //
00493     // Background mode and origin are set so late because of styles
00494     // using the polish() method to modify these settings.
00495     //
00496     // Of course this hack can safely be removed when real transparency
00497     // will be available
00498 
00499     if( !d->topLevel )
00500     {
00501         TQMenuBar::drawContents(p);
00502     }
00503     else
00504     {
00505         bool up_enabled = isUpdatesEnabled();
00506         BackgroundMode bg_mode = backgroundMode();
00507         BackgroundOrigin bg_origin = backgroundOrigin();
00508         
00509         setUpdatesEnabled(false);
00510         setBackgroundMode(X11ParentRelative);
00511         setBackgroundOrigin(WindowOrigin);
00512 
00513     p->eraseRect( rect() );
00514     erase();
00515         
00516         TQColorGroup g = colorGroup();
00517         bool e;
00518 
00519         for ( int i=0; i<(int)count(); i++ )
00520         {
00521             TQMenuItem *mi = findItem( idAt( i ) );
00522 
00523             if ( !mi->text().isNull() || mi->pixmap() )
00524             {
00525                 TQRect r = itemRect(i);
00526                 if(r.isEmpty() || !mi->isVisible())
00527                     continue;
00528 
00529                 e = mi->isEnabledAndVisible();
00530                 if ( e )
00531                     g = isEnabled() ? ( isActiveWindow() ? palette().active() :
00532                                         palette().inactive() ) : palette().disabled();
00533                 else
00534                     g = palette().disabled();
00535 
00536                 bool item_active = ( actItem ==  i );
00537 
00538                 p->setClipRect(r);
00539 
00540                 if( item_active )
00541                 {
00542                     TQStyle::SFlags flags = TQStyle::Style_Default;
00543                     if (isEnabled() && e)
00544                         flags |= TQStyle::Style_Enabled;
00545                     if ( item_active )
00546                         flags |= TQStyle::Style_Active;
00547                     if ( item_active && actItemDown )
00548                         flags |= TQStyle::Style_Down;
00549                     flags |= TQStyle::Style_HasFocus;
00550 
00551                     style().drawControl(TQStyle::CE_MenuBarItem, p, this,
00552                                         r, g, flags, TQStyleOption(mi));
00553                 }
00554                 else
00555                 {
00556                     style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
00557                                      g, e, mi->pixmap(), mi->text());
00558                 }
00559             }
00560         }
00561 
00562         setBackgroundOrigin(bg_origin);
00563         setBackgroundMode(bg_mode);
00564         setUpdatesEnabled(up_enabled);
00565     }
00566 }
00567 
00568 void KMenuBar::virtual_hook( int, void* )
00569 { /*BASE::virtual_hook( id, data );*/ }
00570 
00571 #include "kmenubar.moc"

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdeui

Skip menu "kdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for kdeui by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |