• 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 
70 class KMenuBar::KMenuBarPrivate
71 {
72 public:
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
105 static Atom selection_atom = None;
106 static Atom msg_type_atom = None;
107 
108 static
109 void 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 
122 Atom 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 
133 KMenuBar::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 ( kapp )
146  // toolbarAppearanceChanged(int) is sent when changing macstyle
147  connect( kapp, TQ_SIGNAL(toolbarAppearanceChanged(int)),
148  this, TQ_SLOT(slotReadConfig()));
149 
150  slotReadConfig();
151 }
152 
153 KMenuBar::~KMenuBar()
154 {
155  delete d;
156 }
157 
158 void KMenuBar::setTopLevelMenu(bool top_level)
159 {
160  d->forcedTopLevel = top_level;
161  setTopLevelMenuInternal( top_level );
162 }
163 
164 void 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 
225 bool KMenuBar::isTopLevelMenu() const
226 {
227  return d->topLevel;
228 }
229 
230 // KDE4 remove
231 void KMenuBar::show()
232 {
233  TQMenuBar::show();
234 }
235 
236 void KMenuBar::slotReadConfig()
237 {
238  TDEConfig *config = TDEGlobal::config();
239  TDEConfigGroupSaver saver( config, "KDE" );
240  setTopLevelMenuInternal( config->readBoolEntry( "macStyle", false ) );
241 }
242 
243 bool 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
297 void KMenuBar::showEvent( TQShowEvent *e )
298 {
299  TQMenuBar::showEvent(e);
300 }
301 
302 void 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 
327 void 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 (kapp->desktop()->numScreens() < 2)
337  area = kapp->desktop()->geometry();
338  else
339  area = kapp->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 
352 int KMenuBar::block_resize = 0;
353 
354 void 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 
366 void KMenuBar::setGeometry( const TQRect& r )
367 {
368  setGeometry( r.x(), r.y(), r.width(), r.height() );
369 }
370 
371 void 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 
383 void 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 
393 void 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
408 TQSize 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
430 bool 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 
448 void KMenuBar::updateMenuBarSize()
449  {
450  menuContentsChanged(); // trigger invalidating calculated size
451  resize( sizeHint()); // and resize to preferred size
452  }
453 
454 void KMenuBar::setFrameStyle( int style )
455 {
456  if( d->topLevel )
457  d->frameStyle = style;
458  else
459  TQMenuBar::setFrameStyle( style );
460 }
461 
462 void KMenuBar::setLineWidth( int width )
463 {
464  if( d->topLevel )
465  d->lineWidth = width;
466  else
467  TQMenuBar::setLineWidth( width );
468 }
469 
470 void KMenuBar::setMargin( int margin )
471 {
472  if( d->topLevel )
473  d->margin = margin;
474  else
475  TQMenuBar::setMargin( margin );
476 }
477 
478 void 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 
486 void 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 
568 void 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.1
This website is maintained by Timothy Pearson.