Reserve space for topmenus, so there's no flicker, and the space is taken
even with no topmenu shown. Support topmenus only when enabled in kdeglobals. svn path=/trunk/kdebase/kwin/; revision=266531icc-effect-5.14.5
parent
6c3176c74c
commit
1d71c9839b
26
geometry.cpp
26
geometry.cpp
|
@ -82,6 +82,15 @@ void Workspace::updateClientArea( bool force )
|
||||||
else
|
else
|
||||||
new_areas[ (*it)->desktop() ] = new_areas[ (*it)->desktop() ].intersect( r );
|
new_areas[ (*it)->desktop() ] = new_areas[ (*it)->desktop() ].intersect( r );
|
||||||
}
|
}
|
||||||
|
if( topmenu_space != NULL )
|
||||||
|
{
|
||||||
|
QRect topmenu_area = all;
|
||||||
|
topmenu_area.setTop( topMenuHeight());
|
||||||
|
for( int i = 1;
|
||||||
|
i <= numberOfDesktops();
|
||||||
|
++i )
|
||||||
|
new_areas[ i ] = new_areas[ i ].intersect( topmenu_area );
|
||||||
|
}
|
||||||
|
|
||||||
bool changed = force;
|
bool changed = force;
|
||||||
for( int i = 1;
|
for( int i = 1;
|
||||||
|
@ -104,6 +113,7 @@ void Workspace::updateClientArea( bool force )
|
||||||
rootInfo->setWorkArea( i, r );
|
rootInfo->setWorkArea( i, r );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateTopMenuSpaceGeometry();
|
||||||
for( ClientList::ConstIterator it = clients.begin();
|
for( ClientList::ConstIterator it = clients.begin();
|
||||||
it != clients.end();
|
it != clients.end();
|
||||||
++it)
|
++it)
|
||||||
|
@ -337,6 +347,16 @@ void Workspace::unclutterDesktop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Workspace::updateTopMenuSpaceGeometry()
|
||||||
|
{
|
||||||
|
if( !managingTopMenus())
|
||||||
|
return;
|
||||||
|
QRect area;
|
||||||
|
area = clientArea( MaximizeFullArea, QPoint( 0, 0 ), 1 ); // HACK desktop ?
|
||||||
|
area.setHeight( topMenuHeight());
|
||||||
|
topmenu_space->setGeometry( area );
|
||||||
|
}
|
||||||
|
|
||||||
//********************************************
|
//********************************************
|
||||||
// Client
|
// Client
|
||||||
//********************************************
|
//********************************************
|
||||||
|
@ -351,11 +371,9 @@ void Workspace::unclutterDesktop()
|
||||||
QRect Client::adjustedClientArea( const QRect& area ) const
|
QRect Client::adjustedClientArea( const QRect& area ) const
|
||||||
{
|
{
|
||||||
QRect r = area;
|
QRect r = area;
|
||||||
if( isTopMenu() && workspace()->managingTopMenus())
|
// topmenu area is reserved in updateClientArea()
|
||||||
{
|
if( isTopMenu())
|
||||||
r.setTop( r.top() + workspace()->topMenuHeight());
|
|
||||||
return r;
|
return r;
|
||||||
}
|
|
||||||
NETStrut strut = info->strut();
|
NETStrut strut = info->strut();
|
||||||
if ( strut.left > 0 )
|
if ( strut.left > 0 )
|
||||||
r.setLeft( r.left() + (int) strut.left );
|
r.setLeft( r.left() + (int) strut.left );
|
||||||
|
|
42
layers.cpp
42
layers.cpp
|
@ -131,39 +131,55 @@ void Workspace::propagateClients( bool propagate_new_clients )
|
||||||
// when passig pointers around.
|
// when passig pointers around.
|
||||||
|
|
||||||
// restack the windows according to the stacking order
|
// restack the windows according to the stacking order
|
||||||
Window* new_stack = new Window[ stacking_order.count() + 1 ];
|
Window* new_stack = new Window[ stacking_order.count() + 2 ];
|
||||||
int i = 0;
|
int pos = 0;
|
||||||
// Stack all windows under the support window. The support window is
|
// Stack all windows under the support window. The support window is
|
||||||
// not used for anything (besides the NETWM property), and it's not shown,
|
// not used for anything (besides the NETWM property), and it's not shown,
|
||||||
// but it was lowered after kwin startup. Stacking all clients below
|
// but it was lowered after kwin startup. Stacking all clients below
|
||||||
// it ensures that no client will be ever shown above override-redirect
|
// it ensures that no client will be ever shown above override-redirect
|
||||||
// windows (e.g. popups).
|
// windows (e.g. popups).
|
||||||
new_stack[ i++ ] = supportWindow->winId();
|
new_stack[ pos++ ] = supportWindow->winId();
|
||||||
for ( ClientList::ConstIterator it = stacking_order.fromLast(); it != stacking_order.end(); --it)
|
int topmenu_space_pos = 0;
|
||||||
new_stack[i++] = (*it)->frameId();
|
for( ClientList::ConstIterator it = stacking_order.fromLast();
|
||||||
|
it != stacking_order.end();
|
||||||
|
--it )
|
||||||
|
{
|
||||||
|
new_stack[ pos++ ] = (*it)->frameId();
|
||||||
|
if( (*it)->isTopMenu())
|
||||||
|
topmenu_space_pos = pos;
|
||||||
|
}
|
||||||
|
if( topmenu_space != NULL )
|
||||||
|
{ // make sure the topmenu space is below all topmenus, if there are any
|
||||||
|
for( int i = pos;
|
||||||
|
i > topmenu_space_pos;
|
||||||
|
--i )
|
||||||
|
new_stack[ i ] = new_stack[ i - 1 ];
|
||||||
|
new_stack[ topmenu_space_pos ] = topmenu_space->winId();
|
||||||
|
++pos;
|
||||||
|
}
|
||||||
// TODO isn't it too inefficient to restart always all clients?
|
// TODO isn't it too inefficient to restart always all clients?
|
||||||
// TODO don't restack not visible windows?
|
// TODO don't restack not visible windows?
|
||||||
XRestackWindows(qt_xdisplay(), new_stack, i);
|
XRestackWindows(qt_xdisplay(), new_stack, pos);
|
||||||
delete [] new_stack;
|
delete [] new_stack;
|
||||||
|
|
||||||
if ( propagate_new_clients )
|
if ( propagate_new_clients )
|
||||||
{
|
{
|
||||||
cl = new Window[ desktops.count() + clients.count()];
|
cl = new Window[ desktops.count() + clients.count()];
|
||||||
i = 0;
|
pos = 0;
|
||||||
// TODO this is still not completely in the map order
|
// TODO this is still not completely in the map order
|
||||||
for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it )
|
for ( ClientList::ConstIterator it = desktops.begin(); it != desktops.end(); ++it )
|
||||||
cl[i++] = (*it)->window();
|
cl[pos++] = (*it)->window();
|
||||||
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it )
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it )
|
||||||
cl[i++] = (*it)->window();
|
cl[pos++] = (*it)->window();
|
||||||
rootInfo->setClientList( cl, i );
|
rootInfo->setClientList( cl, pos );
|
||||||
delete [] cl;
|
delete [] cl;
|
||||||
}
|
}
|
||||||
|
|
||||||
cl = new Window[ stacking_order.count()];
|
cl = new Window[ stacking_order.count()];
|
||||||
i = 0;
|
pos = 0;
|
||||||
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
|
for ( ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
|
||||||
cl[i++] = (*it)->window();
|
cl[pos++] = (*it)->window();
|
||||||
rootInfo->setClientListStacking( cl, i );
|
rootInfo->setClientListStacking( cl, pos );
|
||||||
delete [] cl;
|
delete [] cl;
|
||||||
|
|
||||||
#if 0 // not necessary anymore?
|
#if 0 // not necessary anymore?
|
||||||
|
|
|
@ -146,6 +146,13 @@ unsigned long Options::updateSettings()
|
||||||
globalConfig.setGroup("KDE");
|
globalConfig.setGroup("KDE");
|
||||||
fade_tooltips = globalConfig.readBoolEntry("EffectFadeTooltip", false);
|
fade_tooltips = globalConfig.readBoolEntry("EffectFadeTooltip", false);
|
||||||
animate_tooltips = globalConfig.readBoolEntry("EffectAnimateTooltip", false);
|
animate_tooltips = globalConfig.readBoolEntry("EffectAnimateTooltip", false);
|
||||||
|
topmenus = globalConfig.readBoolEntry( "macStyle", false );
|
||||||
|
|
||||||
|
KConfig kdesktopcfg( "kdesktoprc", true );
|
||||||
|
kdesktopcfg.setGroup( "Menubar" );
|
||||||
|
desktop_topmenu = kdesktopcfg.readBoolEntry( "ShowMenubar", false );
|
||||||
|
if( desktop_topmenu )
|
||||||
|
topmenus = true;
|
||||||
|
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -253,6 +253,9 @@ class Options : public KDecorationOptions
|
||||||
*/
|
*/
|
||||||
int electricBorderDelay();
|
int electricBorderDelay();
|
||||||
|
|
||||||
|
bool topMenuEnabled() const { return topmenus; }
|
||||||
|
bool desktopTopMenu() const { return desktop_topmenu; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WindowOperation OpTitlebarDblClick;
|
WindowOperation OpTitlebarDblClick;
|
||||||
|
|
||||||
|
@ -276,6 +279,8 @@ class Options : public KDecorationOptions
|
||||||
int electric_borders;
|
int electric_borders;
|
||||||
int electric_border_delay;
|
int electric_border_delay;
|
||||||
bool show_geometry_tip;
|
bool show_geometry_tip;
|
||||||
|
bool topmenus;
|
||||||
|
bool desktop_topmenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Options* options;
|
extern Options* options;
|
||||||
|
|
|
@ -296,26 +296,25 @@ void Workspace::init()
|
||||||
topmenu_selection = new KSelectionOwner( topmenu_atom );
|
topmenu_selection = new KSelectionOwner( topmenu_atom );
|
||||||
topmenu_watcher = new KSelectionWatcher( topmenu_atom );
|
topmenu_watcher = new KSelectionWatcher( topmenu_atom );
|
||||||
topmenu_height = 0;
|
topmenu_height = 0;
|
||||||
if( topmenu_selection->claim( false ))
|
managing_topmenus = false;
|
||||||
{
|
topmenu_space = NULL;
|
||||||
managing_topmenus = true;
|
|
||||||
connect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
managing_topmenus = false;
|
|
||||||
connect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
|
|
||||||
}
|
|
||||||
// kdDebug() << "TOPMENU INIT:" << managing_topmenus << endl;
|
|
||||||
|
|
||||||
{ // begin updates blocker block
|
{ // begin updates blocker block
|
||||||
StackingUpdatesBlocker blocker( this );
|
StackingUpdatesBlocker blocker( this );
|
||||||
|
|
||||||
|
if( options->topMenuEnabled() && topmenu_selection->claim( false ))
|
||||||
|
setupTopMenuHandling(); // this can call updateStackingOrder()
|
||||||
|
else
|
||||||
|
lostTopMenuSelection();
|
||||||
|
|
||||||
XQueryTree(qt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
|
XQueryTree(qt_xdisplay(), root, &root_return, &parent_return, &wins, &nwins);
|
||||||
for (i = 0; i < nwins; i++)
|
for (i = 0; i < nwins; i++)
|
||||||
{
|
{
|
||||||
XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
|
XGetWindowAttributes(qt_xdisplay(), wins[i], &attr);
|
||||||
if (attr.override_redirect )
|
if (attr.override_redirect )
|
||||||
continue;
|
continue;
|
||||||
|
if( topmenu_space && topmenu_space->winId() == wins[ i ] )
|
||||||
|
continue;
|
||||||
if (attr.map_state != IsUnmapped)
|
if (attr.map_state != IsUnmapped)
|
||||||
{
|
{
|
||||||
if ( addSystemTrayWin( wins[i] ) )
|
if ( addSystemTrayWin( wins[i] ) )
|
||||||
|
@ -400,6 +399,7 @@ Workspace::~Workspace()
|
||||||
delete initPositioning;
|
delete initPositioning;
|
||||||
delete topmenu_watcher;
|
delete topmenu_watcher;
|
||||||
delete topmenu_selection;
|
delete topmenu_selection;
|
||||||
|
delete topmenu_space;
|
||||||
_self = 0;
|
_self = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,14 +505,15 @@ void Workspace::updateCurrentTopMenu()
|
||||||
{
|
{
|
||||||
// toplevel menubar handling
|
// toplevel menubar handling
|
||||||
Client* menubar = 0;
|
Client* menubar = 0;
|
||||||
|
bool block_desktop_menubar = false;
|
||||||
if( active_client )
|
if( active_client )
|
||||||
{
|
{
|
||||||
// show the new menu bar first...
|
// show the new menu bar first...
|
||||||
Client* menu_client = active_client;
|
Client* menu_client = active_client;
|
||||||
// SELI TODO make this also depend on kdesktop's setting, like in menuapplet
|
|
||||||
bool block_desktop_menubar = active_client->isFullScreen();
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
|
if( menu_client->isFullScreen())
|
||||||
|
block_desktop_menubar = true;
|
||||||
for( ClientList::ConstIterator it = menu_client->transients().begin();
|
for( ClientList::ConstIterator it = menu_client->transients().begin();
|
||||||
it != menu_client->transients().end();
|
it != menu_client->transients().end();
|
||||||
++it )
|
++it )
|
||||||
|
@ -524,30 +525,26 @@ void Workspace::updateCurrentTopMenu()
|
||||||
if( menubar != NULL || !menu_client->isTransient())
|
if( menubar != NULL || !menu_client->isTransient())
|
||||||
break;
|
break;
|
||||||
if( menu_client->isModal() || menu_client->transientFor() == NULL )
|
if( menu_client->isModal() || menu_client->transientFor() == NULL )
|
||||||
{ // don't use mainwindow's menu if this is modal or group transient
|
break; // don't use mainwindow's menu if this is modal or group transient
|
||||||
if( menu_client->isModal() || menu_client->groupTransient())
|
|
||||||
block_desktop_menubar = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
menu_client = menu_client->transientFor();
|
menu_client = menu_client->transientFor();
|
||||||
}
|
}
|
||||||
if( !menubar && active_client->keepAbove())
|
}
|
||||||
block_desktop_menubar = true;
|
if( !options->desktopTopMenu())
|
||||||
if( !menubar && !block_desktop_menubar )
|
block_desktop_menubar = true;
|
||||||
|
if( !menubar && !block_desktop_menubar )
|
||||||
|
{
|
||||||
|
// Find the menubar of the desktop
|
||||||
|
Client* desktop = findDesktop( true, currentDesktop());
|
||||||
|
if( desktop != NULL )
|
||||||
{
|
{
|
||||||
// Find the menubar of the desktop
|
for( ClientList::ConstIterator it = desktop->transients().begin();
|
||||||
Client* desktop = findDesktop( true, currentDesktop());
|
it != desktop->transients().end();
|
||||||
if( desktop != NULL )
|
++it )
|
||||||
{
|
if( (*it)->isTopMenu())
|
||||||
for( ClientList::ConstIterator it = desktop->transients().begin();
|
|
||||||
it != desktop->transients().end();
|
|
||||||
++it )
|
|
||||||
if( (*it)->isTopMenu())
|
|
||||||
{
|
{
|
||||||
menubar = *it;
|
menubar = *it;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,7 +566,7 @@ void Workspace::updateCurrentTopMenu()
|
||||||
(*it)->hideClient( true );
|
(*it)->hideClient( true );
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// TODO there should be a blank area where topmenus are placed, no need to keep
|
// There's a blank area where topmenus are placed, no need to keep
|
||||||
// the desktop one always visible
|
// the desktop one always visible
|
||||||
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
|
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
|
||||||
{
|
{
|
||||||
|
@ -729,13 +726,28 @@ void Workspace::slotReconfigure()
|
||||||
else
|
else
|
||||||
destroyBorderWindows();
|
destroyBorderWindows();
|
||||||
|
|
||||||
|
if( options->topMenuEnabled())
|
||||||
|
{
|
||||||
|
if( !managingTopMenus() && topmenu_selection->claim( false ))
|
||||||
|
setupTopMenuHandling();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( managingTopMenus())
|
||||||
|
{
|
||||||
|
topmenu_selection->release();
|
||||||
|
lostTopMenuSelection();
|
||||||
|
}
|
||||||
|
}
|
||||||
topmenu_height = 0; // invalidate used menu height
|
topmenu_height = 0; // invalidate used menu height
|
||||||
if( managingTopMenus())
|
if( managingTopMenus())
|
||||||
{
|
{
|
||||||
|
updateTopMenuSpaceGeometry();
|
||||||
for( ClientList::ConstIterator it = topmenus.begin();
|
for( ClientList::ConstIterator it = topmenus.begin();
|
||||||
it != topmenus.end();
|
it != topmenus.end();
|
||||||
++it )
|
++it )
|
||||||
(*it)->checkWorkspacePosition();
|
(*it)->checkWorkspacePosition();
|
||||||
|
updateCurrentTopMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1815,6 +1827,7 @@ void Workspace::addTopMenu( Client* c )
|
||||||
if( minsize > topMenuHeight())
|
if( minsize > topMenuHeight())
|
||||||
{
|
{
|
||||||
topmenu_height = minsize;
|
topmenu_height = minsize;
|
||||||
|
updateTopMenuSpaceGeometry();
|
||||||
for( ClientList::ConstIterator it = topmenus.begin();
|
for( ClientList::ConstIterator it = topmenus.begin();
|
||||||
it != topmenus.end();
|
it != topmenus.end();
|
||||||
++it )
|
++it )
|
||||||
|
@ -1837,9 +1850,13 @@ void Workspace::removeTopMenu( Client* c )
|
||||||
void Workspace::lostTopMenuSelection()
|
void Workspace::lostTopMenuSelection()
|
||||||
{
|
{
|
||||||
// kdDebug() << "lost TopMenu selection" << endl;
|
// kdDebug() << "lost TopMenu selection" << endl;
|
||||||
|
if( !managing_topmenus )
|
||||||
|
return;
|
||||||
connect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
|
connect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
|
||||||
disconnect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
|
disconnect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
|
||||||
managing_topmenus = false;
|
managing_topmenus = false;
|
||||||
|
delete topmenu_space;
|
||||||
|
updateClientArea();
|
||||||
for( ClientList::ConstIterator it = topmenus.begin();
|
for( ClientList::ConstIterator it = topmenus.begin();
|
||||||
it != topmenus.end();
|
it != topmenus.end();
|
||||||
++it )
|
++it )
|
||||||
|
@ -1855,9 +1872,20 @@ void Workspace::lostTopMenuOwner()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// kdDebug() << "claimed TopMenu selection" << endl;
|
// kdDebug() << "claimed TopMenu selection" << endl;
|
||||||
|
setupTopMenuHandling();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspace::setupTopMenuHandling()
|
||||||
|
{
|
||||||
|
if( managing_topmenus )
|
||||||
|
return;
|
||||||
connect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
|
connect( topmenu_selection, SIGNAL( lostOwnership()), this, SLOT( lostTopMenuSelection()));
|
||||||
disconnect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
|
disconnect( topmenu_watcher, SIGNAL( lostOwner()), this, SLOT( lostTopMenuOwner()));
|
||||||
managing_topmenus = true;
|
managing_topmenus = true;
|
||||||
|
topmenu_space = new QWidget;
|
||||||
|
updateTopMenuSpaceGeometry();
|
||||||
|
topmenu_space->show();
|
||||||
|
updateClientArea();
|
||||||
for( ClientList::ConstIterator it = topmenus.begin();
|
for( ClientList::ConstIterator it = topmenus.begin();
|
||||||
it != topmenus.end();
|
it != topmenus.end();
|
||||||
++it )
|
++it )
|
||||||
|
|
|
@ -341,6 +341,8 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
||||||
void updateCurrentTopMenu();
|
void updateCurrentTopMenu();
|
||||||
void addTopMenu( Client* c );
|
void addTopMenu( Client* c );
|
||||||
void removeTopMenu( Client* c );
|
void removeTopMenu( Client* c );
|
||||||
|
void setupTopMenuHandling();
|
||||||
|
void updateTopMenuSpaceGeometry();
|
||||||
void updateToolWindows( bool also_hide );
|
void updateToolWindows( bool also_hide );
|
||||||
|
|
||||||
// this is the right way to create a new client
|
// this is the right way to create a new client
|
||||||
|
@ -502,6 +504,7 @@ class Workspace : public QObject, public KWinInterface, public KDecorationDefine
|
||||||
KSelectionWatcher* topmenu_watcher;
|
KSelectionWatcher* topmenu_watcher;
|
||||||
ClientList topmenus; // doesn't own them
|
ClientList topmenus; // doesn't own them
|
||||||
mutable int topmenu_height;
|
mutable int topmenu_height;
|
||||||
|
QWidget* topmenu_space;
|
||||||
|
|
||||||
int set_active_client_recursion;
|
int set_active_client_recursion;
|
||||||
int block_stacking_updates; // when >0, stacking updates are temporarily disabled
|
int block_stacking_updates; // when >0, stacking updates are temporarily disabled
|
||||||
|
|
Loading…
Reference in New Issue