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

tdeui

  • tdeui
tdemenubar.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 1997, 1998, 1999, 2000 Sven Radej (radej@kde.org)
3 Copyright (C) 1997, 1998, 1999, 2000 Matthias Ettrich (ettrich@kde.org)
4 Copyright (C) 1999, 2000 Daniel "Mosfet" Duley (mosfet@kde.org)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22
23#ifndef INCLUDE_MENUITEM_DEF
24#define INCLUDE_MENUITEM_DEF
25#endif
26
27#include "config.h"
28#include <tqevent.h>
29#include <tqobjectlist.h>
30#include <tqaccel.h>
31#include <tqpainter.h>
32#include <tqstyle.h>
33#include <tqtimer.h>
34
35#include <tdeconfig.h>
36#include <tdeglobalsettings.h>
37#include <tdemenubar.h>
38#include <tdeapplication.h>
39#include <tdeglobal.h>
40#include <kdebug.h>
41#include <kmanagerselection.h>
42
43#ifdef TQ_WS_X11
44#include <twin.h>
45#include <twinmodule.h>
46#include <qxembed.h>
47
48#include <X11/Xlib.h>
49#include <X11/Xutil.h>
50#include <X11/Xatom.h>
51
52#ifndef None
53#define None 0L
54#endif
55#endif
56
57/*
58
59 Toplevel menubar (not for the fallback size handling done by itself):
60 - should not alter position or set strut
61 - every toplevel must have at most one matching topmenu
62 - embedder won't allow shrinking below a certain size
63 - must have WM_TRANSIENT_FOR pointing the its mainwindow
64 - the exception is desktop's menubar, which can be transient for root window
65 because of using root window as the desktop window
66 - Fitts' Law
67
68*/
69
70class KMenuBar::KMenuBarPrivate
71{
72public:
73 KMenuBarPrivate()
74 : forcedTopLevel( false ),
75 topLevel( false ),
76 wasTopLevel( false ),
77#ifdef TQ_WS_X11
78 selection( NULL ),
79#endif
80 min_size( 0, 0 )
81 {
82 }
83 ~KMenuBarPrivate()
84 {
85#ifdef TQ_WS_X11
86 delete selection;
87#endif
88 }
89 bool forcedTopLevel;
90 bool topLevel;
91 bool wasTopLevel; // when TLW is fullscreen, remember state
92 int frameStyle; // only valid in toplevel mode
93 int lineWidth; // dtto
94 int margin; // dtto
95 bool fallback_mode; // dtto
96#ifdef TQ_WS_X11
97 TDESelectionWatcher* selection;
98#endif
99 TQTimer selection_timer;
100 TQSize min_size;
101 static Atom makeSelectionAtom();
102};
103
104#ifdef TQ_WS_X11
105static Atom selection_atom = None;
106static Atom msg_type_atom = None;
107
108static
109void initAtoms()
110{
111 char nm[ 100 ];
112 sprintf( nm, "_KDE_TOPMENU_OWNER_S%d", DefaultScreen( tqt_xdisplay()));
113 char nm2[] = "_KDE_TOPMENU_MINSIZE";
114 char* names[ 2 ] = { nm, nm2 };
115 Atom atoms[ 2 ];
116 XInternAtoms( tqt_xdisplay(), names, 2, False, atoms );
117 selection_atom = atoms[ 0 ];
118 msg_type_atom = atoms[ 1 ];
119}
120#endif
121
122Atom KMenuBar::KMenuBarPrivate::makeSelectionAtom()
123{
124#ifdef TQ_WS_X11
125 if( selection_atom == None )
126 initAtoms();
127 return selection_atom;
128#else
129 return 0;
130#endif
131}
132
133KMenuBar::KMenuBar(TQWidget *parent, const char *name)
134 : TQMenuBar(parent, name)
135{
136#ifdef TQ_WS_X11
137 QXEmbed::initialize();
138#endif
139 d = new KMenuBarPrivate;
140 connect( &d->selection_timer, TQ_SIGNAL( timeout()),
141 this, TQ_SLOT( selectionTimeout()));
142
143 connect( tqApp->desktop(), TQ_SIGNAL( resized( int )), TQ_SLOT( updateFallbackSize()));
144
145 if ( tdeApp )
146 // toolbarAppearanceChanged(int) is sent when changing macstyle
147 connect( tdeApp, TQ_SIGNAL(toolbarAppearanceChanged(int)),
148 this, TQ_SLOT(slotReadConfig()));
149
150 slotReadConfig();
151}
152
153KMenuBar::~KMenuBar()
154{
155 delete d;
156}
157
158void KMenuBar::setTopLevelMenu(bool top_level)
159{
160 d->forcedTopLevel = top_level;
161 setTopLevelMenuInternal( top_level );
162}
163
164void KMenuBar::setTopLevelMenuInternal(bool top_level)
165{
166 if (d->forcedTopLevel)
167 top_level = true;
168
169 d->wasTopLevel = top_level;
170 if( parentWidget()
171 && parentWidget()->topLevelWidget()->isFullScreen())
172 top_level = false;
173
174 if ( isTopLevelMenu() == top_level )
175 return;
176 d->topLevel = top_level;
177 if ( isTopLevelMenu() )
178 {
179#ifdef TQ_WS_X11
180 d->selection = new TDESelectionWatcher( KMenuBarPrivate::makeSelectionAtom(),
181 DefaultScreen( tqt_xdisplay()));
182 connect( d->selection, TQ_SIGNAL( newOwner( Window )),
183 this, TQ_SLOT( updateFallbackSize()));
184 connect( d->selection, TQ_SIGNAL( lostOwner()),
185 this, TQ_SLOT( updateFallbackSize()));
186#endif
187 d->frameStyle = frameStyle();
188 d->lineWidth = lineWidth();
189 d->margin = margin();
190 d->fallback_mode = false;
191 bool wasShown = !isHidden();
192 reparent( parentWidget(), (WFlags)(WType_TopLevel | WStyle_Tool | WStyle_Customize | WStyle_NoBorder), TQPoint(0,0), false );
193#ifdef TQ_WS_X11
194 KWin::setType( winId(), NET::TopMenu );
195 if( parentWidget())
196 XSetTransientForHint( tqt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
197#endif
198 TQMenuBar::setFrameStyle( NoFrame );
199 TQMenuBar::setLineWidth( 0 );
200 TQMenuBar::setMargin( 0 );
201 updateFallbackSize();
202 d->min_size = TQSize( 0, 0 );
203 if( parentWidget() && !parentWidget()->isTopLevel())
204 setShown( parentWidget()->isVisible());
205 else if ( wasShown )
206 show();
207 } else
208 {
209#ifdef TQ_WS_X11
210 delete d->selection;
211 d->selection = NULL;
212#endif
213 setBackgroundMode( PaletteButton );
214 setFrameStyle( d->frameStyle );
215 setLineWidth( d->lineWidth );
216 setMargin( d->margin );
217 setMinimumSize( 0, 0 );
218 setMaximumSize( TQWIDGETSIZE_MAX, TQWIDGETSIZE_MAX );
219 updateMenuBarSize();
220 if ( parentWidget() )
221 reparent( parentWidget(), TQPoint(0,0), !isHidden());
222 }
223}
224
225bool KMenuBar::isTopLevelMenu() const
226{
227 return d->topLevel;
228}
229
230// KDE4 remove
231void KMenuBar::show()
232{
233 TQMenuBar::show();
234}
235
236void KMenuBar::slotReadConfig()
237{
238 TDEConfig *config = TDEGlobal::config();
239 TDEConfigGroupSaver saver( config, "KDE" );
240 setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
241}
242
243bool KMenuBar::eventFilter(TQObject *obj, TQEvent *ev)
244{
245 if ( d->topLevel )
246 {
247 if ( parentWidget() && obj == parentWidget()->topLevelWidget() )
248 {
249 if( ev->type() == TQEvent::Resize )
250 return false; // ignore resizing of parent, TQMenuBar would try to adjust size
251 if ( ev->type() == TQEvent::Accel || ev->type() == TQEvent::AccelAvailable )
252 {
253 if ( TQApplication::sendEvent( topLevelWidget(), ev ) )
254 return true;
255 }
256 if(ev->type() == TQEvent::ShowFullScreen )
257 // will update the state properly
258 setTopLevelMenuInternal( d->topLevel );
259 }
260 if( parentWidget() && obj == parentWidget() && ev->type() == TQEvent::Reparent )
261 {
262#ifdef TQ_WS_X11
263 XSetTransientForHint( tqt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
264#else
265 //TODO: WIN32?
266#endif
267 setShown( parentWidget()->isTopLevel() || parentWidget()->isVisible());
268 }
269 if( parentWidget() && !parentWidget()->isTopLevel() && obj == parentWidget())
270 { // if the parent is not toplevel, KMenuBar needs to match its visibility status
271 if( ev->type() == TQEvent::Show )
272 {
273#ifdef TQ_WS_X11
274 XSetTransientForHint( tqt_xdisplay(), winId(), parentWidget()->topLevelWidget()->winId());
275#else
276 //TODO: WIN32?
277#endif
278 show();
279 }
280 if( ev->type() == TQEvent::Hide )
281 hide();
282 }
283 }
284 else
285 {
286 if( parentWidget() && obj == parentWidget()->topLevelWidget())
287 {
288 if( ev->type() == TQEvent::WindowStateChange
289 && !parentWidget()->topLevelWidget()->isFullScreen() )
290 setTopLevelMenuInternal( d->wasTopLevel );
291 }
292 }
293 return TQMenuBar::eventFilter( obj, ev );
294}
295
296// KDE4 remove
297void KMenuBar::showEvent( TQShowEvent *e )
298{
299 TQMenuBar::showEvent(e);
300}
301
302void KMenuBar::updateFallbackSize()
303{
304 if( !d->topLevel )
305 return;
306#ifdef TQ_WS_X11
307 if( d->selection->owner() != None )
308#endif
309 { // somebody is managing us, don't mess anything, undo changes
310 // done in fallback mode if needed
311 d->selection_timer.stop();
312 if( d->fallback_mode )
313 {
314 d->fallback_mode = false;
315 KWin::setStrut( winId(), 0, 0, 0, 0 );
316 setMinimumSize( 0, 0 );
317 setMaximumSize( TQWIDGETSIZE_MAX, TQWIDGETSIZE_MAX );
318 updateMenuBarSize();
319 }
320 return;
321 }
322 if( d->selection_timer.isActive())
323 return;
324 d->selection_timer.start( 100, true );
325}
326
327void KMenuBar::selectionTimeout()
328{ // nobody is managing us, handle resizing
329 if ( d->topLevel )
330 {
331 d->fallback_mode = true; // KMenuBar is handling its position itself
332 TDEConfigGroup xineramaConfig(TDEGlobal::config(),"Xinerama");
333 int screen = xineramaConfig.readNumEntry("MenubarScreen",
334 TQApplication::desktop()->screenNumber(TQPoint(0,0)) );
335 TQRect area;
336 if (tdeApp->desktop()->numScreens() < 2)
337 area = tdeApp->desktop()->geometry();
338 else
339 area = tdeApp->desktop()->screenGeometry(screen);
340 int margin = 0;
341 move(area.left() - margin, area.top() - margin);
342 setFixedSize(area.width() + 2* margin , heightForWidth( area.width() + 2 * margin ) );
343#ifdef TQ_WS_X11
344 int strut_height = height() - margin;
345 if( strut_height < 0 )
346 strut_height = 0;
347 KWin::setStrut( winId(), 0, 0, strut_height, 0 );
348#endif
349 }
350}
351
352int KMenuBar::block_resize = 0;
353
354void KMenuBar::resizeEvent( TQResizeEvent *e )
355{
356 if( e->spontaneous() && d->topLevel && !d->fallback_mode )
357 {
358 ++block_resize; // do not respond with configure request to ConfigureNotify event
359 TQMenuBar::resizeEvent(e); // to avoid possible infinite loop
360 --block_resize;
361 }
362 else
363 TQMenuBar::resizeEvent(e);
364}
365
366void KMenuBar::setGeometry( const TQRect& r )
367{
368 setGeometry( r.x(), r.y(), r.width(), r.height() );
369}
370
371void KMenuBar::setGeometry( int x, int y, int w, int h )
372{
373 if( block_resize > 0 )
374 {
375 move( x, y );
376 return;
377 }
378 checkSize( w, h );
379 if( geometry() != TQRect( x, y, w, h ))
380 TQMenuBar::setGeometry( x, y, w, h );
381}
382
383void KMenuBar::resize( int w, int h )
384{
385 if( block_resize > 0 )
386 return;
387 checkSize( w, h );
388 if( size() != TQSize( w, h ))
389 TQMenuBar::resize( w, h );
390// kdDebug() << "RS:" << w << ":" << h << ":" << width() << ":" << height() << ":" << minimumWidth() << ":" << minimumHeight() << endl;
391}
392
393void KMenuBar::checkSize( int& w, int& h )
394{
395 if( !d->topLevel || d->fallback_mode )
396 return;
397 TQSize s = sizeHint();
398 w = s.width();
399 h = s.height();
400 // This is not done as setMinimumSize(), because that would set the minimum
401 // size in WM_NORMAL_HINTS, and KWin would not allow changing to smaller size
402 // anymore
403 w = KMAX( w, d->min_size.width());
404 h = KMAX( h, d->min_size.height());
405}
406
407// QMenuBar's sizeHint() gives wrong size (insufficient width), which causes wrapping in the kicker applet
408TQSize KMenuBar::sizeHint() const
409{
410 if( !d->topLevel || block_resize > 0 )
411 return TQMenuBar::sizeHint();
412 // Since TQMenuBar::sizeHint() may indirectly call resize(),
413 // avoid infinite recursion.
414 ++block_resize;
415 // find the minimum useful height, and enlarge the width until the menu fits in that height (one row)
416 int h = heightForWidth( 1000000 );
417 int w = TQMenuBar::sizeHint().width();
418 // optimization - don't call heightForWidth() too many times
419 while( heightForWidth( w + 12 ) > h )
420 w += 12;
421 while( heightForWidth( w + 4 ) > h )
422 w += 4;
423 while( heightForWidth( w ) > h )
424 ++w;
425 --block_resize;
426 return TQSize( w, h );
427}
428
429#ifdef TQ_WS_X11
430bool KMenuBar::x11Event( XEvent* ev )
431{
432 if( ev->type == ClientMessage && ev->xclient.message_type == msg_type_atom
433 && ev->xclient.window == winId())
434 {
435 // TQMenuBar is trying really hard to keep the size it deems right.
436 // Forcing minimum size and blocking resizing to match parent size
437 // in checkResizingToParent() seem to be the only way to make
438 // KMenuBar keep the size it wants
439 d->min_size = TQSize( ev->xclient.data.l[ 1 ], ev->xclient.data.l[ 2 ] );
440// kdDebug() << "MINSIZE:" << d->min_size << endl;
441 updateMenuBarSize();
442 return true;
443 }
444 return TQMenuBar::x11Event( ev );
445}
446#endif
447
448void KMenuBar::updateMenuBarSize()
449 {
450 menuContentsChanged(); // trigger invalidating calculated size
451 resize( sizeHint()); // and resize to preferred size
452 }
453
454void KMenuBar::setFrameStyle( int style )
455{
456 if( d->topLevel )
457 d->frameStyle = style;
458 else
459 TQMenuBar::setFrameStyle( style );
460}
461
462void KMenuBar::setLineWidth( int width )
463{
464 if( d->topLevel )
465 d->lineWidth = width;
466 else
467 TQMenuBar::setLineWidth( width );
468}
469
470void KMenuBar::setMargin( int margin )
471{
472 if( d->topLevel )
473 d->margin = margin;
474 else
475 TQMenuBar::setMargin( margin );
476}
477
478void KMenuBar::closeEvent( TQCloseEvent* e )
479{
480 if( d->topLevel )
481 e->ignore(); // mainly for the fallback mode
482 else
483 TQMenuBar::closeEvent( e );
484}
485
486void KMenuBar::drawContents( TQPainter* p )
487{
488 // Closes the BR77113
489 // We need to overload this method to paint only the menu items
490 // This way when the KMenuBar is embedded in the menu applet it
491 // integrates correctly.
492 //
493 // Background mode and origin are set so late because of styles
494 // using the polish() method to modify these settings.
495 //
496 // Of course this hack can safely be removed when real transparency
497 // will be available
498
499 if( !d->topLevel )
500 {
501 TQMenuBar::drawContents(p);
502 }
503 else
504 {
505 bool up_enabled = isUpdatesEnabled();
506 BackgroundMode bg_mode = backgroundMode();
507 BackgroundOrigin bg_origin = backgroundOrigin();
508
509 setUpdatesEnabled(false);
510 setBackgroundMode(X11ParentRelative);
511 setBackgroundOrigin(WindowOrigin);
512
513 p->eraseRect( rect() );
514 erase();
515
516 TQColorGroup g = colorGroup();
517 bool e;
518
519 for ( int i=0; i<(int)count(); i++ )
520 {
521 TQMenuItem *mi = findItem( idAt( i ) );
522
523 if ( !mi->text().isNull() || mi->pixmap() )
524 {
525 TQRect r = itemRect(i);
526 if(r.isEmpty() || !mi->isVisible())
527 continue;
528
529 e = mi->isEnabledAndVisible();
530 if ( e )
531 g = isEnabled() ? ( isActiveWindow() ? palette().active() :
532 palette().inactive() ) : palette().disabled();
533 else
534 g = palette().disabled();
535
536 bool item_active = ( actItem == i );
537
538 p->setClipRect(r);
539
540 if( item_active )
541 {
542 TQStyle::SFlags flags = TQStyle::Style_Default;
543 if (isEnabled() && e)
544 flags |= TQStyle::Style_Enabled;
545 if ( item_active )
546 flags |= TQStyle::Style_Active;
547 if ( item_active && actItemDown )
548 flags |= TQStyle::Style_Down;
549 flags |= TQStyle::Style_HasFocus;
550
551 style().drawControl(TQStyle::CE_MenuBarItem, p, this,
552 r, g, flags, TQStyleOption(mi));
553 }
554 else
555 {
556 style().drawItem(p, r, AlignCenter | AlignVCenter | ShowPrefix,
557 g, e, mi->pixmap(), mi->text());
558 }
559 }
560 }
561
562 setBackgroundOrigin(bg_origin);
563 setBackgroundMode(bg_mode);
564 setUpdatesEnabled(up_enabled);
565 }
566}
567
568void KMenuBar::virtual_hook( int, void* )
569{ /*BASE::virtual_hook( id, data );*/ }
570
571#include "tdemenubar.moc"
KMenuBar::setTopLevelMenu
void setTopLevelMenu(bool top_level=true)
This controls whether or not this menubar will be a top-level bar similar to the way Macintosh handle...
Definition: tdemenubar.cpp:158
KMenuBar::isTopLevelMenu
bool isTopLevelMenu() const
Is our menubar a top-level (Macintosh style) menubar?
Definition: tdemenubar.cpp:225
KWin::setType
static void setType(WId win, NET::WindowType windowType)
KWin::setStrut
static void setStrut(WId win, int left, int right, int top, int bottom)
TDEConfigBase::readBoolEntry
bool readBoolEntry(const TQString &pKey, bool bDefault=false) const
TDEConfigGroupSaver
TDEConfigGroup
TDEConfig
TDEGlobal::config
static TDEConfig * config()
KMAX
#define KMAX(a, b)
TDEStdAccel::name
TQString name(StdAccel id)

tdeui

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

tdeui

Skip menu "tdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.9.4
This website is maintained by Timothy Pearson.