20 #include "workspace.h"
22 #include <tdeapplication.h>
23 #include <tdeglobal.h>
24 #include <tqpainter.h>
27 #include "placement.h"
28 #include "notifications.h"
29 #include "geometrytip.h"
32 namespace KWinInternal
42 void Workspace::desktopResized()
45 TQRect geom = TDEApplication::desktop()->geometry();
46 NETSize desktop_geometry;
47 desktop_geometry.width = geom.width();
48 desktop_geometry.height = geom.height();
49 rootInfo->setDesktopGeometry( -1, desktop_geometry );
51 updateClientArea(
true );
52 destroyActiveBorders();
53 updateActiveBorders();
59 void Workspace::kDestopResized()
76 void Workspace::updateClientArea(
bool force )
78 TQDesktopWidget *desktopwidget = TDEApplication::desktop();
79 int nscreens = desktopwidget -> numScreens ();
81 TQRect* new_wareas =
new TQRect[ numberOfDesktops() + 1 ];
82 TQRect** new_sareas =
new TQRect*[ numberOfDesktops() + 1];
83 TQRect* screens =
new TQRect [ nscreens ];
84 TQRect desktopArea = desktopwidget -> geometry ();
89 screens [iS] = desktopwidget -> screenGeometry (iS);
92 i <= numberOfDesktops();
95 new_wareas[ i ] = desktopArea;
96 new_sareas[ i ] =
new TQRect [ nscreens ];
100 new_sareas[ i ][ iS ] = screens[ iS ];
102 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
104 if( !(*it)->hasStrut())
106 TQRect r = (*it)->adjustedClientArea( desktopArea, desktopArea );
107 if( (*it)->isOnAllDesktops())
109 i <= numberOfDesktops();
112 new_wareas[ i ] = new_wareas[ i ].intersect( r );
116 new_sareas[ i ][ iS ] =
117 new_sareas[ i ][ iS ].intersect(
118 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
123 new_wareas[ (*it)->desktop() ] = new_wareas[ (*it)->desktop() ].intersect( r );
129 new_sareas[ (*it)->desktop() ][ iS ] =
130 new_sareas[ (*it)->desktop() ][ iS ].intersect(
131 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
138 i <= numberOfDesktops();
144 kdDebug () <<
"new_sarea: " << new_sareas[ i ][ iS ] << endl;
148 if( topmenu_space != NULL )
150 TQRect topmenu_area = desktopArea;
151 topmenu_area.setTop( topMenuHeight());
153 i <= numberOfDesktops();
155 new_wareas[ i ] = new_wareas[ i ].intersect( topmenu_area );
158 bool changed = force;
164 !changed && i <= numberOfDesktops();
167 if( workarea[ i ] != new_wareas[ i ] )
172 if (new_sareas[ i ][ iS ] != screenarea [ i ][ iS ])
179 workarea = new_wareas;
182 screenarea = new_sareas;
185 for(
int i = 1; i <= numberOfDesktops(); i++)
187 r.pos.x = workarea[ i ].x();
188 r.pos.y = workarea[ i ].y();
189 r.size.width = workarea[ i ].width();
190 r.size.height = workarea[ i ].height();
191 rootInfo->setWorkArea( i, r );
194 updateTopMenuGeometry();
195 for( ClientList::ConstIterator it = clients.begin();
198 (*it)->checkWorkspacePosition();
199 for( ClientList::ConstIterator it = desktops.begin();
200 it != desktops.end();
202 (*it)->checkWorkspacePosition();
209 void Workspace::updateClientArea()
211 updateClientArea(
false );
222 TQRect Workspace::clientArea( clientAreaOption opt,
int screen,
int desktop )
const
224 if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
225 desktop = currentDesktop();
226 TQDesktopWidget *desktopwidget = kapp->desktop();
227 TQRect sarea = screenarea
228 ? screenarea[ desktop ][ screen ]
229 : desktopwidget->screenGeometry( screen );
230 TQRect warea = workarea[ desktop ].isNull()
231 ? kapp->desktop()->geometry()
232 : workarea[ desktop ];
236 if (options->xineramaMaximizeEnabled)
237 if (desktopwidget->numScreens() < 2)
243 case MaximizeFullArea:
244 if (options->xineramaMaximizeEnabled)
245 if (desktopwidget->numScreens() < 2)
246 return desktopwidget->geometry();
248 return desktopwidget->screenGeometry( screen );
250 return desktopwidget->geometry();
252 if (options->xineramaFullscreenEnabled)
253 if (desktopwidget->numScreens() < 2)
254 return desktopwidget->geometry();
256 return desktopwidget->screenGeometry( screen );
258 return desktopwidget->geometry();
260 if (options->xineramaPlacementEnabled)
261 if (desktopwidget->numScreens() < 2)
268 if (options->xineramaMovementEnabled)
269 if (desktopwidget->numScreens() < 2)
270 return desktopwidget->geometry();
272 return desktopwidget->screenGeometry( screen );
274 return desktopwidget->geometry();
278 return desktopwidget->geometry();
280 if (desktopwidget->numScreens() < 2)
281 return desktopwidget->geometry();
283 return desktopwidget->screenGeometry( screen );
289 TQRect Workspace::clientArea( clientAreaOption opt,
const TQPoint& p,
int desktop )
const
291 TQDesktopWidget *desktopwidget = TDEApplication::desktop();
292 int screen = desktopwidget->screenNumber( p );
294 screen = desktopwidget->primaryScreen();
295 return clientArea( opt, screen, desktop );
298 TQRect Workspace::clientArea( clientAreaOption opt,
const Client* c )
const
300 return clientArea( opt, c->geometry().center(), c->desktop());
309 TQPoint Workspace::adjustClientPosition( Client* c, TQPoint pos )
314 if (options->windowSnapZone || options->borderSnapZone )
316 const bool sOWO=options->snapOnlyWhenOverlapping;
317 const TQRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
318 const int xmin = maxRect.left();
319 const int xmax = maxRect.right()+1;
320 const int ymin = maxRect.top();
321 const int ymax = maxRect.bottom()+1;
323 const int cx(pos.x());
324 const int cy(pos.y());
325 const int cw(c->width());
326 const int ch(c->height());
334 int lx, ly, lrx, lry;
337 int snap = options->borderSnapZone;
340 if ((sOWO?(cx<xmin):
true) && (TQABS(xmin-cx)<snap))
345 if ((sOWO?(rx>xmax):
true) && (TQABS(rx-xmax)<snap) && (TQABS(xmax-rx) < deltaX))
351 if ((sOWO?(cy<ymin):
true) && (TQABS(ymin-cy)<snap))
356 if ((sOWO?(ry>ymax):
true) && (TQABS(ry-ymax)<snap) && (TQABS(ymax-ry) < deltaY))
364 snap = options->windowSnapZone;
367 TQValueList<Client *>::ConstIterator l;
368 for (l = clients.begin();l != clients.end();++l )
370 if ((*l)->isOnDesktop(currentDesktop()) &&
376 lrx = lx + (*l)->width();
377 lry = ly + (*l)->height();
379 if ( (( cy <= lry ) && ( cy >= ly )) ||
380 (( ry >= ly ) && ( ry <= lry )) ||
381 (( cy <= ly ) && ( ry >= lry )) )
383 if ((sOWO?(cx<lrx):
true) && (TQABS(lrx-cx)<snap) && ( TQABS(lrx -cx) < deltaX) )
385 deltaX = TQABS( lrx - cx );
388 if ((sOWO?(rx>lx):
true) && (TQABS(rx-lx)<snap) && ( TQABS( rx - lx )<deltaX) )
390 deltaX = TQABS(rx - lx);
395 if ( (( cx <= lrx ) && ( cx >= lx )) ||
396 (( rx >= lx ) && ( rx <= lrx )) ||
397 (( cx <= lx ) && ( rx >= lrx )) )
399 if ((sOWO?(cy<lry):
true) && (TQABS(lry-cy)<snap) && (TQABS( lry -cy ) < deltaY))
401 deltaY = TQABS( lry - cy );
405 if ((sOWO?(ry>ly):
true) && (TQABS(ry-ly)<snap) && (TQABS( ry - ly ) < deltaY ))
407 deltaY = TQABS( ry - ly );
414 pos = TQPoint(nx, ny);
419 TQRect Workspace::adjustClientSize( Client* c, TQRect moveResizeGeom,
int mode )
424 if ( options->windowSnapZone || options->borderSnapZone )
426 const bool sOWO=options->snapOnlyWhenOverlapping;
428 const TQRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop());
429 const int xmin = maxRect.left();
430 const int xmax = maxRect.right();
431 const int ymin = maxRect.top();
432 const int ymax = maxRect.bottom();
434 const int cx(moveResizeGeom.left());
435 const int cy(moveResizeGeom.top());
436 const int rx(moveResizeGeom.right());
437 const int ry(moveResizeGeom.bottom());
439 int newcx(cx), newcy(cy);
440 int newrx(rx), newry(ry);
444 int lx, ly, lrx, lry;
447 int snap = options->borderSnapZone;
453 #define SNAP_BORDER_TOP \
454 if ((sOWO?(newcy<ymin):true) && (TQABS(ymin-newcy)<deltaY)) \
456 deltaY = TQABS(ymin-newcy); \
460 #define SNAP_BORDER_BOTTOM \
461 if ((sOWO?(newry>ymax):true) && (TQABS(ymax-newry)<deltaY)) \
463 deltaY = TQABS(ymax-newcy); \
467 #define SNAP_BORDER_LEFT \
468 if ((sOWO?(newcx<xmin):true) && (TQABS(xmin-newcx)<deltaX)) \
470 deltaX = TQABS(xmin-newcx); \
474 #define SNAP_BORDER_RIGHT \
475 if ((sOWO?(newrx>xmax):true) && (TQABS(xmax-newrx)<deltaX)) \
477 deltaX = TQABS(xmax-newrx); \
482 case PositionBottomRight:
492 case PositionTopLeft:
502 case PositionTopRight:
506 case PositionBottomLeft:
519 snap = options->windowSnapZone;
524 TQValueList<Client *>::ConstIterator l;
525 for (l = clients.begin();l != clients.end();++l )
527 if ((*l)->isOnDesktop(currentDesktop()) &&
533 lrx =(*l)->x() + (*l)->width();
534 lry =(*l)->y() + (*l)->height();
536 #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
537 (( newry >= ly ) && ( newry <= lry )) || \
538 (( newcy <= ly ) && ( newry >= lry )) )
540 #define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
541 (( rx >= lx ) && ( rx <= lrx )) || \
542 (( cx <= lx ) && ( rx >= lrx )) )
544 #define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
546 && (TQABS( lry - newcy ) < deltaY) ) { \
547 deltaY = TQABS( lry - newcy ); \
551 #define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
553 && (TQABS( ly - newry ) < deltaY) ) { \
554 deltaY = TQABS( ly - newry ); \
558 #define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
560 && (TQABS( lrx - newcx ) < deltaX)) { \
561 deltaX = TQABS( lrx - newcx ); \
565 #define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
567 && (TQABS( lx - newrx ) < deltaX)) \
569 deltaX = TQABS( lx - newrx ); \
575 case PositionBottomRight:
585 case PositionTopLeft:
595 case PositionTopRight:
599 case PositionBottomLeft:
610 moveResizeGeom = TQRect(TQPoint(newcx, newcy), TQPoint(newrx, newry));
612 return moveResizeGeom;
618 void Workspace::setClientIsMoving( Client *c )
620 Q_ASSERT(!c || !movingClient);
632 void Workspace::cascadeDesktop()
635 Q_ASSERT( block_stacking_updates == 0 );
636 ClientList::ConstIterator it(stackingOrder().begin());
637 initPositioning->reinitCascading( currentDesktop());
638 TQRect area = clientArea( PlacementArea, TQPoint( 0, 0 ), currentDesktop());
639 for (; it != stackingOrder().end(); ++it)
641 if((!(*it)->isOnDesktop(currentDesktop())) ||
642 ((*it)->isMinimized()) ||
643 ((*it)->isOnAllDesktops()) ||
644 (!(*it)->isMovable()) )
646 initPositioning->placeCascaded(*it, area);
654 void Workspace::unclutterDesktop()
656 ClientList::Iterator it(clients.fromLast());
657 for (; it != clients.end(); --it)
659 if((!(*it)->isOnDesktop(currentDesktop())) ||
660 ((*it)->isMinimized()) ||
661 ((*it)->isOnAllDesktops()) ||
662 (!(*it)->isMovable()) )
664 initPositioning->placeSmart(*it, TQRect());
669 void Workspace::updateTopMenuGeometry( Client* c )
671 if( !managingTopMenus())
676 ev.xclient.display = tqt_xdisplay();
677 ev.xclient.type = ClientMessage;
678 ev.xclient.window = c->window();
679 static Atom msg_type_atom = XInternAtom( tqt_xdisplay(),
"_KDE_TOPMENU_MINSIZE", False );
680 ev.xclient.message_type = msg_type_atom;
681 ev.xclient.format = 32;
682 ev.xclient.data.l[0] = get_tqt_x_time();
683 ev.xclient.data.l[1] = topmenu_space->width();
684 ev.xclient.data.l[2] = topmenu_space->height();
685 ev.xclient.data.l[3] = 0;
686 ev.xclient.data.l[4] = 0;
687 XSendEvent( tqt_xdisplay(), c->window(), False, NoEventMask, &ev );
688 KWin::setStrut( c->window(), 0, 0, topmenu_height, 0 );
689 c->checkWorkspacePosition();
694 area = clientArea( MaximizeFullArea, TQPoint( 0, 0 ), 1 );
695 area.setHeight( topMenuHeight());
696 topmenu_space->setGeometry( area );
697 for( ClientList::ConstIterator it = topmenus.begin();
698 it != topmenus.end();
700 updateTopMenuGeometry( *it );
708 void Client::keepInArea( TQRect area,
bool partial )
713 area.setLeft( TQMIN( area.left() - width() + 100, area.left()));
714 area.setTop( TQMIN( area.top() - height() + 100, area.top()));
715 area.setRight( TQMAX( area.right() + width() - 100, area.right()));
716 area.setBottom( TQMAX( area.bottom() + height() - 100, area.bottom()));
718 if ( geometry().right() > area.right() && width() < area.width() )
719 move( area.right() - width(), y() );
720 if ( geometry().bottom() > area.bottom() && height() < area.height() )
721 move( x(), area.bottom() - height() );
722 if( !area.contains( geometry().topLeft() ))
747 NETExtendedStrut str = strut();
748 TQRect stareaL = TQRect(
752 str . left_end - str . left_start + 1 );
753 TQRect stareaR = TQRect (
754 desktopArea . right () - str . right_width + 1,
757 str . right_end - str . right_start + 1 );
758 TQRect stareaT = TQRect (
761 str . top_end - str . top_start + 1,
763 TQRect stareaB = TQRect (
765 desktopArea . bottom () - str . bottom_width + 1,
766 str . bottom_end - str . bottom_start + 1,
769 NETExtendedStrut ext = info->extendedStrut();
770 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
771 && ( str.left_width != 0 || str.right_width != 0 || str.top_width != 0 || str.bottom_width != 0 )) {
779 if (stareaT.top() == geometry().top() && stareaT.bottom() == geometry().bottom()) {
780 stareaT.setLeft(geometry().left());
781 stareaT.setRight(geometry().right());
784 if (stareaB.top() == geometry().top() && stareaB.bottom() == geometry().bottom()) {
785 stareaB.setLeft(geometry().left());
786 stareaB.setRight(geometry().right());
789 if (stareaL.left() == geometry().left() && stareaL.right() == geometry().right()) {
790 stareaL.setTop(geometry().top());
791 stareaL.setBottom(geometry().bottom());
794 if (stareaR.left() == geometry().left() && stareaR.right() == geometry().right()) {
795 stareaR.setTop(geometry().top());
796 stareaR.setBottom(geometry().bottom());
801 TQRect screenarea = workspace()->clientArea( ScreenArea,
this );
805 if( area == kapp->desktop()->geometry())
807 if( stareaL.left() < screenarea.left())
809 if( stareaR.right() > screenarea.right())
811 if( stareaT.top() < screenarea.top())
813 if( stareaB.bottom() < screenarea.bottom())
819 stareaL.setLeft( KMAX( stareaL.left(), screenarea.left()));
820 stareaR.setRight( KMIN( stareaR.right(), screenarea.right()));
821 stareaT.setTop( KMAX( stareaT.top(), screenarea.top()));
822 stareaB.setBottom( KMIN( stareaB.bottom(), screenarea.bottom()));
824 if (stareaL . intersects (area)) {
826 r . setLeft( stareaL . right() + 1 );
828 if (stareaR . intersects (area)) {
830 r . setRight( stareaR . left() - 1 );
832 if (stareaT . intersects (area)) {
834 r . setTop( stareaT . bottom() + 1 );
836 if (stareaB . intersects (area)) {
838 r . setBottom( stareaB . top() - 1 );
843 NETExtendedStrut Client::strut()
const
845 NETExtendedStrut ext = info->extendedStrut();
846 NETStrut str = info->strut();
847 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
848 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 ))
853 ext.left_width = str.left;
855 ext.left_end = XDisplayHeight( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
859 ext.right_width = str.right;
861 ext.right_end = XDisplayHeight( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
865 ext.top_width = str.top;
867 ext.top_end = XDisplayWidth( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
869 if( str.bottom != 0 )
871 ext.bottom_width = str.bottom;
872 ext.bottom_start = 0;
873 ext.bottom_end = XDisplayWidth( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
879 bool Client::hasStrut()
const
881 NETExtendedStrut ext = strut();
882 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 )
889 void Client::updateWorkareaDiffs()
891 TQRect area = workspace()->clientArea( WorkArea,
this );
892 TQRect geom = geometry();
893 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
894 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
905 int Client::computeWorkareaDiff(
int left,
int right,
int a_left,
int a_right )
907 int left_diff = left - a_left;
908 int right_diff = a_right - right;
909 if( left_diff < 0 || right_diff < 0 )
914 int max_diff = ( a_right - a_left ) / 10;
915 if( left_diff < right_diff )
916 return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
917 else if( left_diff > right_diff )
918 return right_diff < max_diff ? right_diff + 1 : INT_MAX;
923 void Client::checkWorkspacePosition()
927 TQRect area = workspace()->clientArea( FullArea,
this );
928 if( geometry() != area )
934 TQRect area = workspace()->clientArea( FullScreenArea,
this );
935 if( geometry() != area )
943 if( workspace()->managingTopMenus())
946 ClientList mainclients = mainClients();
947 if( mainclients.count() == 1 )
948 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
950 area = workspace()->clientArea( MaximizeFullArea, TQPoint( 0, 0 ),
desktop());
951 area.setHeight( workspace()->topMenuHeight());
958 if( maximizeMode() != MaximizeRestore )
960 changeMaximize(
false,
false,
true );
964 int old_diff_x = workarea_diff_x;
965 int old_diff_y = workarea_diff_y;
966 updateWorkareaDiffs();
973 if( workspace()->initializing())
976 TQRect area = workspace()->clientArea( WorkArea,
this );
977 TQRect new_geom = geometry();
978 TQRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
979 TQRect tmp_area_x( area.left(), 0, area.width(), 0 );
980 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
982 TQRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
983 TQRect tmp_area_y( area.top(), 0, area.height(), 0 );
984 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
985 new_geom = TQRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
986 TQRect final_geom( new_geom.topLeft(),
adjustedSize( new_geom.size()));
987 if( final_geom != new_geom )
989 if( old_diff_x != INT_MAX && old_diff_x > 0 )
990 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
991 if( old_diff_y != INT_MAX && old_diff_y > 0 )
992 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
994 if( final_geom != geometry() )
1010 void Client::checkDirection(
int new_diff,
int old_diff, TQRect& rect,
const TQRect& area )
1012 if( old_diff != INT_MIN )
1014 if( old_diff == INT_MAX )
1016 if( new_diff == INT_MIN )
1018 rect.setLeft( area.left());
1019 rect.setRight( area.right());
1026 rect.moveLeft( area.left() + ( -old_diff - 1 ));
1028 rect.moveRight( area.right() - ( old_diff - 1 ));
1033 rect.setLeft( area.left() + ( -old_diff - 1 ) );
1035 rect.setRight( area.right() - ( old_diff - 1 ));
1038 rect.setWidth( area.width());
1041 if( rect.left() < area.left())
1042 rect.moveLeft( area.left());
1043 else if( rect.right() > area.right())
1044 rect.moveRight( area.right());
1047 if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
1051 if( rect.left() < area.left() + 5 )
1052 rect.moveRight( area.left() + 5 );
1053 if( rect.right() > area.right() - 5 )
1054 rect.moveLeft( area.right() - 5 );
1057 if (!moveResizeMode && options->shadowEnabled(isActive()))
1062 drawIntersectingShadows();
1063 if (options->shadowEnabled(isActive()))
1064 drawDelayedShadow();
1071 TQSize Client::adjustedSize(
const TQSize& frame, Sizemode mode )
const
1075 TQSize wsize( frame.width() - ( border_left + border_right ),
1076 frame.height() - ( border_top + border_bottom ));
1077 if( wsize.isEmpty())
1078 wsize = TQSize( 1, 1 );
1080 return sizeForClientSize( wsize, mode,
false );
1085 TQSize Client::adjustedSize()
const
1087 return sizeForClientSize( clientSize());
1098 TQSize Client::sizeForClientSize(
const TQSize& wsize, Sizemode mode,
bool noframe )
const
1100 int w = wsize.width();
1101 int h = wsize.height();
1102 if( w < 1 || h < 1 )
1104 kdWarning() <<
"sizeForClientSize() with empty size!" << endl;
1105 kdWarning() << kdBacktrace() << endl;
1112 TQSize min_size = minSize();
1113 TQSize max_size = maxSize();
1114 if( decoration != NULL )
1116 TQSize decominsize = decoration->minimumSize();
1117 TQSize border_size( border_left + border_right, border_top + border_bottom );
1118 if( border_size.width() > decominsize.width())
1119 decominsize.setWidth( border_size.width());
1120 if( border_size.height() > decominsize.height())
1121 decominsize.setHeight( border_size.height());
1122 if( decominsize.width() > min_size.width())
1123 min_size.setWidth( decominsize.width());
1124 if( decominsize.height() > min_size.height())
1125 min_size.setHeight( decominsize.height());
1127 w = TQMIN( max_size.width(), w );
1128 h = TQMIN( max_size.height(), h );
1129 w = TQMAX( min_size.width(), w );
1130 h = TQMAX( min_size.height(), h );
1134 int width_inc = xSizeHint.width_inc;
1135 int height_inc = xSizeHint.height_inc;
1136 int basew_inc = xSizeHint.min_width;
1137 int baseh_inc = xSizeHint.min_height;
1138 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
1139 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
1155 if( xSizeHint.flags & PAspect )
1157 double min_aspect_w = xSizeHint.min_aspect.x;
1158 double min_aspect_h = xSizeHint.min_aspect.y;
1159 double max_aspect_w = xSizeHint.max_aspect.x;
1160 double max_aspect_h = xSizeHint.max_aspect.y;
1164 w -= xSizeHint.base_width;
1165 h -= xSizeHint.base_height;
1166 int max_width = max_size.width() - xSizeHint.base_width;
1167 int min_width = min_size.width() - xSizeHint.base_width;
1168 int max_height = max_size.height() - xSizeHint.base_height;
1169 int min_height = min_size.height() - xSizeHint.base_height;
1170 #define ASPECT_CHECK_GROW_W \
1171 if( min_aspect_w * h > min_aspect_h * w ) \
1173 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
1174 if( w + delta <= max_width ) \
1177 #define ASPECT_CHECK_SHRINK_H_GROW_W \
1178 if( min_aspect_w * h > min_aspect_h * w ) \
1180 int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
1181 if( h - delta >= min_height ) \
1185 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
1186 if( w + delta <= max_width ) \
1190 #define ASPECT_CHECK_GROW_H \
1191 if( max_aspect_w * h < max_aspect_h * w ) \
1193 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
1194 if( h + delta <= max_height ) \
1197 #define ASPECT_CHECK_SHRINK_W_GROW_H \
1198 if( max_aspect_w * h < max_aspect_h * w ) \
1200 int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
1201 if( w - delta >= min_width ) \
1205 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
1206 if( h + delta <= max_height ) \
1216 ASPECT_CHECK_SHRINK_H_GROW_W
1217 ASPECT_CHECK_SHRINK_W_GROW_H
1223 case SizemodeFixedW:
1227 ASPECT_CHECK_SHRINK_H_GROW_W
1228 ASPECT_CHECK_SHRINK_W_GROW_H
1232 case SizemodeFixedH:
1235 ASPECT_CHECK_SHRINK_W_GROW_H
1236 ASPECT_CHECK_SHRINK_H_GROW_W
1243 ASPECT_CHECK_SHRINK_H_GROW_W
1244 ASPECT_CHECK_SHRINK_W_GROW_H
1250 #undef ASPECT_CHECK_SHRINK_H_GROW_W
1251 #undef ASPECT_CHECK_SHRINK_W_GROW_H
1252 #undef ASPECT_CHECK_GROW_W
1253 #undef ASPECT_CHECK_GROW_H
1254 w += xSizeHint.base_width;
1255 h += xSizeHint.base_height;
1257 if( !rules()->checkStrictGeometry(
false ))
1260 if( maximizeMode() & MaximizeHorizontal )
1262 if( maximizeMode() & MaximizeVertical )
1268 w += border_left + border_right;
1269 h += border_top + border_bottom;
1271 return rules()->checkSize( TQSize( w, h ));
1277 void Client::getWmNormalHints()
1280 if (XGetWMNormalHints(tqt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
1281 xSizeHint.flags = 0;
1284 if( ! ( xSizeHint.flags & PMinSize ))
1285 xSizeHint.min_width = xSizeHint.min_height = 0;
1286 if( xSizeHint.flags & PBaseSize )
1291 if( ! ( xSizeHint.flags & PMinSize ))
1293 xSizeHint.min_width = xSizeHint.base_width;
1294 xSizeHint.min_height = xSizeHint.base_height;
1298 xSizeHint.base_width = xSizeHint.base_height = 0;
1299 if( ! ( xSizeHint.flags & PMaxSize ))
1300 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
1303 xSizeHint.max_width = TQMAX( xSizeHint.max_width, 1 );
1304 xSizeHint.max_height = TQMAX( xSizeHint.max_height, 1 );
1306 if( xSizeHint.flags & PResizeInc )
1308 xSizeHint.width_inc = kMax( xSizeHint.width_inc, 1 );
1309 xSizeHint.height_inc = kMax( xSizeHint.height_inc, 1 );
1313 xSizeHint.width_inc = 1;
1314 xSizeHint.height_inc = 1;
1316 if( xSizeHint.flags & PAspect )
1318 xSizeHint.min_aspect.y = kMax( xSizeHint.min_aspect.y, 1 );
1319 xSizeHint.max_aspect.y = kMax( xSizeHint.max_aspect.y, 1 );
1323 xSizeHint.min_aspect.x = 1;
1324 xSizeHint.min_aspect.y = INT_MAX;
1325 xSizeHint.max_aspect.x = INT_MAX;
1326 xSizeHint.max_aspect.y = 1;
1328 if( ! ( xSizeHint.flags & PWinGravity ))
1329 xSizeHint.win_gravity = NorthWestGravity;
1333 if( new_size != size() && !isFullScreen())
1335 TQRect orig_geometry = geometry();
1336 resizeWithChecks( new_size );
1337 if( ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
1341 TQRect area = workspace()->clientArea( MovementArea,
this );
1342 if( area.contains( orig_geometry ))
1344 area = workspace()->clientArea( WorkArea,
this );
1345 if( area.contains( orig_geometry ))
1350 updateAllowedActions();
1353 TQSize Client::minSize()
const
1355 return rules()->checkMinSize( TQSize( xSizeHint.min_width, xSizeHint.min_height ));
1358 TQSize Client::maxSize()
const
1360 return rules()->checkMaxSize( TQSize( xSizeHint.max_width, xSizeHint.max_height ));
1368 void Client::sendSyntheticConfigureNotify()
1371 c.type = ConfigureNotify;
1372 c.send_event = True;
1374 c.window = window();
1375 c.x = x() + clientPos().x();
1376 c.y = y() + clientPos().y();
1377 c.width = clientSize().width();
1378 c.height = clientSize().height();
1381 c.override_redirect = 0;
1382 XSendEvent( tqt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
1385 const TQPoint Client::calculateGravitation(
bool invert,
int gravity )
const
1391 gravity = xSizeHint.win_gravity;
1396 case NorthWestGravity:
1405 case NorthEastGravity:
1423 case SouthWestGravity:
1425 dy = -border_bottom;
1429 dy = -border_bottom;
1431 case SouthEastGravity:
1433 dy = -border_bottom;
1436 if( gravity != CenterGravity )
1443 dx = - ( border_left + border_right ) / 2;
1444 dy = - ( border_top + border_bottom ) / 2;
1447 return TQPoint( x() + dx, y() + dy );
1449 return TQPoint( x() - dx, y() - dy );
1452 void Client::configureRequest(
int value_mask,
int rx,
int ry,
int rw,
int rh,
int gravity,
bool from_tool )
1454 inhibitConfigureRequests =
true;
1455 configureRequestTimer->start(100,
true);
1457 gravity = xSizeHint.win_gravity;
1458 if( value_mask & ( CWX | CWY ))
1460 TQPoint new_pos = calculateGravitation(
true, gravity );
1461 if ( value_mask & CWX )
1463 if ( value_mask & CWY )
1470 if ( new_pos.x() == x() + clientPos().x() && new_pos.y() == y() + clientPos().y()
1471 && gravity == NorthWestGravity && !from_tool )
1477 int nw = clientSize().width();
1478 int nh = clientSize().height();
1479 if ( value_mask & CWWidth )
1481 if ( value_mask & CWHeight )
1483 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
1484 new_pos = rules()->checkPosition( new_pos );
1487 if ( maximizeMode() != MaximizeFull
1490 TQRect orig_geometry = geometry();
1491 GeometryUpdatesPostponer blocker(
this );
1494 setGeometry( TQRect( calculateGravitation(
false, gravity ), size()));
1495 updateFullScreenHack( TQRect( new_pos, TQSize( nw, nh )));
1496 TQRect area = workspace()->clientArea( WorkArea,
this );
1497 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
1498 && area.contains( orig_geometry ))
1506 workspace() -> updateClientArea ();
1510 if ( value_mask & (CWWidth | CWHeight )
1511 && ! ( value_mask & ( CWX | CWY )) )
1513 int nw = clientSize().width();
1514 int nh = clientSize().height();
1515 if ( value_mask & CWWidth )
1517 if ( value_mask & CWHeight )
1519 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
1523 TQRect orig_geometry = geometry();
1524 GeometryUpdatesPostponer blocker(
this );
1525 int save_gravity = xSizeHint.win_gravity;
1526 xSizeHint.win_gravity = gravity;
1527 resizeWithChecks( ns );
1528 xSizeHint.win_gravity = save_gravity;
1529 updateFullScreenHack( TQRect( calculateGravitation(
true, xSizeHint.win_gravity ), TQSize( nw, nh )));
1530 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
1534 TQRect area = workspace()->clientArea( MovementArea,
this );
1535 if( area.contains( orig_geometry ))
1537 area = workspace()->clientArea( WorkArea,
this );
1538 if( area.contains( orig_geometry ))
1548 void Client::resizeWithChecks(
int w,
int h, ForceGeometry_t force )
1550 if( shade_geometry_change )
1554 if( h == border_top + border_bottom )
1556 kdWarning() <<
"Shaded geometry passed for size:" << endl;
1557 kdWarning() << kdBacktrace() << endl;
1562 TQRect area = workspace()->clientArea( WorkArea,
this );
1564 if( w > area.width())
1566 if( h > area.height())
1571 switch( xSizeHint.win_gravity )
1573 case NorthWestGravity:
1577 newx = ( newx + width() / 2 ) - ( w / 2 );
1579 case NorthEastGravity:
1580 newx = newx + width() - w;
1583 newy = ( newy + height() / 2 ) - ( h / 2 );
1586 newx = ( newx + width() / 2 ) - ( w / 2 );
1587 newy = ( newy + height() / 2 ) - ( h / 2 );
1593 newx = newx + width() - w;
1594 newy = ( newy + height() / 2 ) - ( h / 2 );
1596 case SouthWestGravity:
1597 newy = newy + height() - h;
1600 newx = ( newx + width() / 2 ) - ( w / 2 );
1601 newy = newy + height() - h;
1603 case SouthEastGravity:
1604 newx = newx + width() - w;
1605 newy = newy + height() - h;
1610 if( workarea_diff_x != INT_MIN && w <= area.width())
1612 if( newx < area.left())
1614 if( newx + w > area.right() + 1 )
1615 newx = area.right() + 1 - w;
1616 assert( newx >= area.left() && newx + w <= area.right() + 1 );
1618 if( workarea_diff_y != INT_MIN && h <= area.height())
1620 if( newy < area.top())
1622 if( newy + h > area.bottom() + 1 )
1623 newy = area.bottom() + 1 - h;
1624 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
1630 void Client::NETMoveResizeWindow(
int flags,
int x,
int y,
int width,
int height )
1632 int gravity = flags & 0xff;
1634 if( flags & ( 1 << 8 ))
1636 if( flags & ( 1 << 9 ))
1638 if( flags & ( 1 << 10 ))
1639 value_mask |= CWWidth;
1640 if( flags & ( 1 << 11 ))
1641 value_mask |= CWHeight;
1642 configureRequest( value_mask, x, y, width, height, gravity,
true );
1651 if( !motif_may_move || isFullScreen())
1653 if( isSpecialWindow() && !isSplash() && !isToolbar())
1655 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
1657 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
1667 if( !motif_may_resize || isFullScreen())
1669 if( isSpecialWindow() )
1671 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
1673 if( rules()->checkSize( TQSize()).isValid())
1676 TQSize min = minSize();
1677 TQSize max = maxSize();
1678 return min.width() < max.width() || min.height() < max.height();
1684 bool Client::isMaximizable()
const
1686 if( isModalSystemNotification())
1690 TemporaryAssign< MaximizeMode > tmp( max_mode, MaximizeRestore );
1694 if ( maximizeMode() != MaximizeRestore )
1696 TQSize max = maxSize();
1698 if( max.width() < 32767 || max.height() < 32767 )
1703 TQSize areasize = workspace()->clientArea( MaximizeArea,
this ).size();
1704 if( max.width() < areasize.width() || max.height() < areasize.height())
1727 if( shade_geometry_change )
1731 if( h == border_top + border_bottom )
1733 kdDebug() <<
"Shaded geometry passed for size:" << endl;
1734 kdDebug() << kdBacktrace() << endl;
1738 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1739 h = border_top + border_bottom;
1744 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1746 if( force == NormalGeometrySet && frame_geometry == TQRect( x, y, w, h ))
1748 frame_geometry = TQRect( x, y, w, h );
1749 updateWorkareaDiffs();
1750 if( postpone_geometry_updates != 0 )
1752 pending_geometry_update =
true;
1755 resizeDecoration( TQSize( w, h ));
1756 XMoveResizeWindow( tqt_xdisplay(), frameId(), x, y, w, h );
1760 TQSize cs = clientSize();
1761 XMoveResizeWindow( tqt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
1762 cs.width(), cs.height());
1763 XMoveResizeWindow( tqt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
1767 updateWorkareaDiffs();
1768 sendSyntheticConfigureNotify();
1769 updateWindowRules();
1770 checkMaximizeGeometry();
1771 workspace()->checkActiveScreen(
this );
1774 void Client::plainResize(
int w,
int h, ForceGeometry_t force )
1777 if( shade_geometry_change )
1781 if( h == border_top + border_bottom )
1783 kdDebug() <<
"Shaded geometry passed for size:" << endl;
1784 kdDebug() << kdBacktrace() << endl;
1788 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1789 h = border_top + border_bottom;
1794 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1796 if( TQSize( w, h ) != rules()->checkSize( TQSize( w, h )))
1798 kdDebug() <<
"forced size fail:" << TQSize( w,h ) <<
":" << rules()->checkSize( TQSize( w, h )) << endl;
1799 kdDebug() << kdBacktrace() << endl;
1801 if( force == NormalGeometrySet && frame_geometry.size() == TQSize( w, h ))
1803 frame_geometry.setSize( TQSize( w, h ));
1804 updateWorkareaDiffs();
1805 if( postpone_geometry_updates != 0 )
1807 pending_geometry_update =
true;
1810 resizeDecoration( TQSize( w, h ));
1811 XResizeWindow( tqt_xdisplay(), frameId(), w, h );
1815 TQSize cs = clientSize();
1816 XMoveResizeWindow( tqt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
1817 cs.width(), cs.height());
1818 XMoveResizeWindow( tqt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
1821 updateWorkareaDiffs();
1822 sendSyntheticConfigureNotify();
1823 updateWindowRules();
1824 checkMaximizeGeometry();
1825 workspace()->checkActiveScreen(
this );
1833 if( force == NormalGeometrySet && frame_geometry.topLeft() == TQPoint( x, y ))
1835 frame_geometry.moveTopLeft( TQPoint( x, y ));
1836 updateWorkareaDiffs();
1837 if( postpone_geometry_updates != 0 )
1839 pending_geometry_update =
true;
1842 XMoveWindow( tqt_xdisplay(), frameId(), x, y );
1843 sendSyntheticConfigureNotify();
1844 updateWindowRules();
1845 checkMaximizeGeometry();
1846 workspace()->checkActiveScreen(
this );
1850 void Client::postponeGeometryUpdates(
bool postpone )
1854 if( postpone_geometry_updates == 0 )
1855 pending_geometry_update =
false;
1856 ++postpone_geometry_updates;
1860 if( --postpone_geometry_updates == 0 )
1862 if( pending_geometry_update )
1865 setGeometry( TQRect( pos(), adjustedSize()), ForceGeometrySet );
1868 pending_geometry_update =
false;
1874 void Client::maximize( MaximizeMode m )
1876 setMaximize( m & MaximizeVertical, m & MaximizeHorizontal );
1885 max_mode & MaximizeVertical ? !vertically : vertically,
1886 max_mode & MaximizeHorizontal ? !horizontally : horizontally,
1890 void Client::changeMaximize(
bool vertical,
bool horizontal,
bool adjust )
1892 if( !isMaximizable())
1895 MaximizeMode old_mode = max_mode;
1900 max_mode = MaximizeMode( max_mode ^ MaximizeVertical );
1902 max_mode = MaximizeMode( max_mode ^ MaximizeHorizontal );
1905 max_mode = rules()->checkMaximize( max_mode );
1906 if( !adjust && max_mode == old_mode )
1909 GeometryUpdatesPostponer blocker(
this );
1912 Q_ASSERT( !( vertical && horizontal )
1913 || ((( max_mode & MaximizeVertical ) != 0 ) == (( max_mode & MaximizeHorizontal ) != 0 )));
1915 TQRect clientArea = workspace()->clientArea( MaximizeArea,
this );
1918 if( !adjust && !( y() == clientArea.top() && height() == clientArea.height()))
1920 geom_restore.setTop( y());
1921 geom_restore.setHeight( height());
1923 if( !adjust && !( x() == clientArea.left() && width() == clientArea.width()))
1925 geom_restore.setLeft( x());
1926 geom_restore.setWidth( width());
1931 if(( vertical && !(old_mode & MaximizeVertical ))
1932 || ( horizontal && !( old_mode & MaximizeHorizontal )))
1933 Notify::raise( Notify::Maximize );
1935 Notify::raise( Notify::UnMaximize );
1938 if( decoration != NULL )
1939 decoration->borders( border_left, border_right, border_top, border_bottom );
1942 if ( old_mode==MaximizeFull && max_mode==MaximizeRestore )
1944 if ( maximizeModeRestore()==MaximizeVertical )
1946 max_mode = MaximizeVertical;
1947 maxmode_restore = MaximizeRestore;
1949 if ( maximizeModeRestore()==MaximizeHorizontal )
1951 max_mode = MaximizeHorizontal;
1952 maxmode_restore = MaximizeRestore;
1959 case MaximizeVertical:
1961 if( old_mode & MaximizeHorizontal )
1963 if( geom_restore.width() == 0 )
1965 plainResize(
adjustedSize(TQSize(width(), clientArea.height()), SizemodeFixedH ));
1966 workspace()->placeSmart(
this, clientArea );
1969 setGeometry( TQRect(TQPoint( geom_restore.x(), clientArea.top()),
1970 adjustedSize(TQSize( geom_restore.width(), clientArea.height()), SizemodeFixedH )), ForceGeometrySet);
1973 setGeometry( TQRect(TQPoint(x(), clientArea.top()),
1974 adjustedSize(TQSize(width(), clientArea.height()), SizemodeFixedH )), ForceGeometrySet);
1975 info->setState( NET::MaxVert, NET::Max );
1979 case MaximizeHorizontal:
1981 if( old_mode & MaximizeVertical )
1983 if( geom_restore.height() == 0 )
1985 plainResize(
adjustedSize(TQSize(clientArea.width(), height()), SizemodeFixedW ));
1986 workspace()->placeSmart(
this, clientArea );
1989 setGeometry( TQRect( TQPoint(clientArea.left(), geom_restore.y()),
1990 adjustedSize(TQSize(clientArea.width(), geom_restore.height()), SizemodeFixedW )), ForceGeometrySet);
1993 setGeometry( TQRect( TQPoint(clientArea.left(), y()),
1994 adjustedSize(TQSize(clientArea.width(), height()), SizemodeFixedW )), ForceGeometrySet);
1995 info->setState( NET::MaxHoriz, NET::Max );
1999 case MaximizeRestore:
2001 TQRect restore = geometry();
2003 if( old_mode & MaximizeVertical )
2005 restore.setTop( geom_restore.top());
2006 restore.setBottom( geom_restore.bottom());
2008 if( old_mode & MaximizeHorizontal )
2010 restore.setLeft( geom_restore.left());
2011 restore.setRight( geom_restore.right());
2013 if( !restore.isValid())
2015 TQSize s = TQSize( clientArea.width()*2/3, clientArea.height()*2/3 );
2016 if( geom_restore.width() > 0 )
2017 s.setWidth( geom_restore.width());
2018 if( geom_restore.height() > 0 )
2019 s.setHeight( geom_restore.height());
2021 workspace()->placeSmart(
this, clientArea );
2022 restore = geometry();
2023 if( geom_restore.width() > 0 )
2024 restore.moveLeft( geom_restore.x());
2025 if( geom_restore.height() > 0 )
2026 restore.moveTop( geom_restore.y());
2029 info->setState( 0, NET::Max );
2037 if( old_mode & MaximizeVertical )
2038 maxmode_restore = MaximizeVertical;
2039 if( old_mode & MaximizeHorizontal )
2040 maxmode_restore = MaximizeHorizontal;
2042 TQSize adjSize =
adjustedSize(clientArea.size(), SizemodeMax );
2043 TQRect r = TQRect(clientArea.topLeft(), adjSize);
2045 info->setState( NET::Max, NET::Max );
2052 updateAllowedActions();
2053 if( decoration != NULL )
2054 decoration->maximizeChange();
2055 updateWindowRules();
2058 void Client::resetMaximize()
2060 if( max_mode == MaximizeRestore )
2062 max_mode = MaximizeRestore;
2063 Notify::raise( Notify::UnMaximize );
2064 info->setState( 0, NET::Max );
2065 updateAllowedActions();
2066 if( decoration != NULL )
2067 decoration->borders( border_left, border_right, border_top, border_bottom );
2069 setGeometry( TQRect( pos(), sizeForClientSize( clientSize())), ForceGeometrySet );
2072 if( decoration != NULL )
2073 decoration->maximizeChange();
2076 void Client::checkMaximizeGeometry()
2082 if( isMove() || isResize())
2085 static int recursion_protection = 0;
2086 if( recursion_protection > 3 )
2088 kdWarning( 1212 ) <<
"Check maximize overflow - you loose!" << endl;
2089 kdWarning( 1212 ) << kdBacktrace() << endl;
2092 ++recursion_protection;
2093 TQRect max_area = workspace()->clientArea( MaximizeArea,
this );
2094 if( geometry() == max_area )
2096 if( max_mode != MaximizeFull )
2097 maximize( MaximizeFull );
2099 else if( x() == max_area.left() && width() == max_area.width())
2101 if( max_mode != MaximizeHorizontal )
2102 maximize( MaximizeHorizontal );
2104 else if( y() == max_area.top() && height() == max_area.height())
2106 if( max_mode != MaximizeVertical )
2107 maximize( MaximizeVertical );
2109 else if( max_mode != MaximizeRestore )
2113 --recursion_protection;
2116 bool Client::isFullScreenable(
bool fullscreen_hack )
const
2118 if( !rules()->checkFullScreen(
true ))
2120 if( fullscreen_hack )
2121 return isNormalWindow();
2122 if( rules()->checkStrictGeometry(
false ))
2125 TQRect fsarea = workspace()->clientArea( FullScreenArea,
this );
2126 if( sizeForClientSize( fsarea.size(), SizemodeAny,
true ) != fsarea.size())
2130 return !isSpecialWindow();
2133 bool Client::userCanSetFullScreen()
const
2135 if( fullscreen_mode == FullScreenHack )
2137 if( !isFullScreenable(
false ))
2140 TemporaryAssign< FullScreenMode > tmp( fullscreen_mode, FullScreenNone );
2141 return isNormalWindow() && isMaximizable();
2144 void Client::setFullScreen(
bool set,
bool user )
2146 if( !isFullScreen() && !set )
2148 if( fullscreen_mode == FullScreenHack )
2150 if( user && !userCanSetFullScreen())
2152 set = rules()->checkFullScreen( set );
2153 setShade( ShadeNone );
2154 bool was_fs = isFullScreen();
2156 geom_fs_restore = geometry();
2157 fullscreen_mode = set ? FullScreenNormal : FullScreenNone;
2158 if( was_fs == isFullScreen())
2160 StackingUpdatesBlocker blocker1( workspace());
2161 GeometryUpdatesPostponer blocker2(
this );
2162 workspace()->updateClientLayer(
this );
2163 info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
2164 updateDecoration(
false,
false );
2166 setGeometry( workspace()->clientArea( FullScreenArea,
this ));
2169 if( !geom_fs_restore.isNull())
2174 setGeometry( workspace()->clientArea( MaximizeArea,
this ));
2177 updateWindowRules();
2180 int Client::checkFullScreenHack(
const TQRect& geom )
const
2183 if( noBorder() && !isUserNoBorder() && isFullScreenable(
true ))
2185 if( geom.size() == workspace()->clientArea( FullArea, geom.center(),
desktop()).size())
2187 if( geom.size() == workspace()->clientArea( ScreenArea, geom.center(),
desktop()).size())
2193 void Client::updateFullScreenHack(
const TQRect& geom )
2195 int type = checkFullScreenHack( geom );
2196 if( fullscreen_mode == FullScreenNone && type != 0 )
2198 fullscreen_mode = FullScreenHack;
2199 updateDecoration(
false,
false );
2201 if( rules()->checkStrictGeometry(
false ))
2204 ? workspace()->clientArea( FullArea, geom.center(),
desktop())
2205 : workspace()->clientArea( ScreenArea, geom.center(),
desktop());
2208 geom = workspace()->clientArea( FullScreenArea, geom.center(),
desktop());
2211 else if( fullscreen_mode == FullScreenHack && type == 0 )
2213 fullscreen_mode = FullScreenNone;
2214 updateDecoration(
false,
false );
2217 StackingUpdatesBlocker blocker( workspace());
2218 workspace()->updateClientLayer(
this );
2221 static TQRect* visible_bound =
nullptr;
2222 static GeometryTip* geometryTip =
nullptr;
2224 void Client::drawbound(
const TQRect& geom )
2226 assert( visible_bound == NULL );
2227 visible_bound =
new TQRect( geom );
2228 doDrawbound( *visible_bound,
false );
2231 void Client::clearbound()
2233 if( visible_bound == NULL )
2235 doDrawbound( *visible_bound,
true );
2236 delete visible_bound;
2240 void Client::doDrawbound(
const TQRect& geom,
bool clear )
2242 if( decoration != NULL && decoration->drawbound( geom, clear ))
2244 TQPainter p ( workspace()->desktopWidget() );
2245 p.setPen( TQPen( TQt::white, 5 ) );
2246 p.setRasterOp( TQt::XorROP );
2252 g.setLeft( g.left() + 2 );
2253 g.setRight( g.right() - 2 );
2255 if( g.height() > 5 )
2257 g.setTop( g.top() + 2 );
2258 g.setBottom( g.bottom() - 2 );
2263 void Client::positionGeometryTip() {
2264 assert(isMove() || isResize());
2267 if (options->showGeometryTip()) {
2270 bool save_under = ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2271 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque );
2272 geometryTip =
new GeometryTip( &xSizeHint, save_under );
2276 TQRect wgeom(isActiveBorderMaximizing() ? activeBorderMaximizeGeometry() : moveResizeGeom);
2277 wgeom.setWidth(wgeom.width() - (width() - clientSize().width()));
2278 wgeom.setHeight(isShade() ? 0 : wgeom.height() - (height() - clientSize().height()));
2280 geometryTip->setGeometry(wgeom);
2281 if (!geometryTip->isVisible()) {
2282 geometryTip->show();
2283 geometryTip->raise();
2288 class EatAllPaintEvents
2292 virtual bool eventFilter( TQObject* o, TQEvent* e )
2293 {
return e->type() == TQEvent::Paint && o != geometryTip; }
2296 static EatAllPaintEvents* eater = 0;
2298 bool Client::startMoveResize()
2300 assert( !moveResizeMode );
2301 assert( TQWidget::keyboardGrabber() == NULL );
2302 assert( TQWidget::mouseGrabber() == NULL );
2303 if( TQApplication::activePopupWidget() != NULL )
2305 bool has_grab =
false;
2309 XSetWindowAttributes attrs;
2310 TQRect r = workspace()->clientArea( FullArea,
this );
2311 move_resize_grab_window = XCreateWindow( tqt_xdisplay(), workspace()->rootWin(), r.x(), r.y(),
2312 r.width(), r.height(), 0, CopyFromParent, InputOnly, CopyFromParent, 0, &attrs );
2313 XMapRaised( tqt_xdisplay(), move_resize_grab_window );
2314 if( XGrabPointer( tqt_xdisplay(), move_resize_grab_window, False,
2315 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
2316 GrabModeAsync, GrabModeAsync, move_resize_grab_window, cursor.handle(), get_tqt_x_time() ) == Success )
2318 if( XGrabKeyboard( tqt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, get_tqt_x_time() ) == Success )
2322 XDestroyWindow( tqt_xdisplay(), move_resize_grab_window );
2323 move_resize_grab_window = None;
2328 moveResizeMode =
true;
2329 initialMoveResizeGeom = geometry();
2334 activeTiled =
false;
2335 if (options->resetMaximizedWindowGeometry() && isMove()) {
2341 activeTiledOrigGeom.moveLeft(TQCursor::pos().x() - (activeTiledOrigGeom.width() / 2));
2342 moveOffset.setX(TQCursor::pos().x() - activeTiledOrigGeom.x());
2348 if ( maximizeMode() != MaximizeRestore )
2350 if (options->resetMaximizedWindowGeometry() && isMove()) {
2351 maximize(MaximizeRestore);
2356 activeTiled =
false;
2359 moveResizeGeom = geometry();
2360 workspace()->setClientIsMoving(
this);
2361 checkUnrestrictedMoveResize();
2364 if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove))
2369 if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque)
2371 savedOpacity_ = opacity_;
2372 setOpacity(options->translucentMovingWindows, options->movingWindowOpacity);
2375 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2376 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
2379 kapp->sendPostedEvents();
2388 Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
2390 if (options->activeBorders() == Options::ActiveSwitchOnMove ||
2391 options->activeBorders() == Options::ActiveTileMaximize ||
2392 options->activeBorders() == Options::ActiveTileOnly)
2395 workspace()->reserveActiveBorderSwitching(
true);
2401 void Client::finishMoveResize(
bool cancel )
2405 if (!isActiveBorderMaximizing()) {
2406 setGeometry(cancel ? initialMoveResizeGeom : moveResizeGeom);
2411 kdDebug() <<
"finishing moveresize in active mode, cancel is " << cancel << endl;
2412 activeMaximizing =
false;
2414 activeTiledOrigGeom = initialMoveResizeGeom;
2417 case ActiveMaximizeMode: {
2419 bool full = (maximizeMode() == MaximizeFull);
2426 : activeBorderMaximizeGeometry());
2428 activeTiledOrigGeom.moveTopLeft(rect().topLeft());
2431 checkMaximizeGeometry();
2433 Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
2436 void Client::leaveMoveResize()
2439 if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque)
2440 setOpacity(
true, savedOpacity_);
2441 if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove))
2446 geometryTip->hide();
2450 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2451 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
2453 XUngrabKeyboard( tqt_xdisplay(), get_tqt_x_time() );
2454 XUngrabPointer( tqt_xdisplay(), get_tqt_x_time() );
2455 XDestroyWindow( tqt_xdisplay(), move_resize_grab_window );
2456 move_resize_grab_window = None;
2457 workspace()->setClientIsMoving(0);
2458 if( move_faked_activity )
2459 workspace()->unfakeActivity(
this );
2460 move_faked_activity =
false;
2461 moveResizeMode =
false;
2464 if (options->shadowEnabled(isActive()))
2466 drawIntersectingShadows();
2467 updateOpacityCache();
2470 if (options->activeBorders() == Options::ActiveSwitchOnMove ||
2471 options->activeBorders() == Options::ActiveTileMaximize ||
2472 options->activeBorders() == Options::ActiveTileOnly)
2474 workspace()->reserveActiveBorderSwitching(
false);
2482 void Client::checkUnrestrictedMoveResize()
2484 if( unrestrictedMoveResize )
2486 TQRect desktopArea = workspace()->clientArea( WorkArea, moveResizeGeom.center(),
desktop());
2487 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
2490 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
2491 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
2493 titlebar_marge = initialMoveResizeGeom.height();
2494 top_marge = border_bottom;
2495 bottom_marge = border_top;
2498 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
2499 unrestrictedMoveResize =
true;
2500 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2501 unrestrictedMoveResize =
true;
2502 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2503 unrestrictedMoveResize =
true;
2504 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2505 unrestrictedMoveResize =
true;
2506 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
2507 unrestrictedMoveResize =
true;
2511 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
2512 unrestrictedMoveResize =
true;
2514 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2515 unrestrictedMoveResize =
true;
2516 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2517 unrestrictedMoveResize =
true;
2518 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2519 unrestrictedMoveResize =
true;
2523 void Client::handleMoveResize(
int x,
int y,
int x_root,
int y_root) {
2524 if ( (mode == PositionCenter && !
isMovable())
2525 || (mode != PositionCenter && (isShade() || !
isResizable())) )
2528 if (!moveResizeMode) {
2529 TQPoint p(TQPoint( x, y ) - moveOffset);
2530 if (p.manhattanLength() >= 6) {
2531 if (!startMoveResize()) {
2541 if ( mode != PositionCenter && shade_mode != ShadeNone )
2542 setShade( ShadeNone );
2544 TQPoint globalPos( x_root, y_root );
2547 TQPoint topleft = globalPos - moveOffset;
2548 TQPoint bottomright = globalPos + invertedMoveOffset;
2549 TQRect previousMoveResizeGeom = moveResizeGeom;
2555 TQRect desktopArea = workspace()->clientArea( WorkArea, globalPos,
desktop());
2556 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
2557 if( unrestrictedMoveResize )
2558 left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
2562 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
2563 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
2565 titlebar_marge = initialMoveResizeGeom.height();
2566 top_marge = border_bottom;
2567 bottom_marge = border_top;
2570 bool update =
false;
2574 TQRect orig = initialMoveResizeGeom;
2575 Sizemode sizemode = SizemodeAny;
2578 case PositionTopLeft:
2579 moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
2581 case PositionBottomRight:
2582 moveResizeGeom = TQRect( orig.topLeft(), bottomright ) ;
2584 case PositionBottomLeft:
2585 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.y() ), TQPoint( orig.right(), bottomright.y()) ) ;
2587 case PositionTopRight:
2588 moveResizeGeom = TQRect( TQPoint( orig.x(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2591 moveResizeGeom = TQRect( TQPoint( orig.left(), topleft.y() ), orig.bottomRight() ) ;
2592 sizemode = SizemodeFixedH;
2594 case PositionBottom:
2595 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( orig.right(), bottomright.y() ) ) ;
2596 sizemode = SizemodeFixedH;
2599 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.top() ), orig.bottomRight() ) ;
2600 sizemode = SizemodeFixedW;
2603 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), orig.bottom() ) ) ;
2604 sizemode = SizemodeFixedW;
2606 case PositionCenter:
2613 moveResizeGeom = workspace()->adjustClientSize(
this, moveResizeGeom, mode );
2616 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
2617 moveResizeGeom.setBottom( desktopArea.top() + top_marge );
2618 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2619 moveResizeGeom.setTop( desktopArea.bottom() - bottom_marge );
2620 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2621 moveResizeGeom.setRight( desktopArea.left() + left_marge );
2622 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2623 moveResizeGeom.setLeft(desktopArea.right() - right_marge );
2624 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
2625 moveResizeGeom.setTop( desktopArea.top());
2627 TQSize size =
adjustedSize( moveResizeGeom.size(), sizemode );
2629 topleft = TQPoint( moveResizeGeom.right() - size.width() + 1, moveResizeGeom.bottom() - size.height() + 1 );
2630 bottomright = TQPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
2631 orig = moveResizeGeom;
2634 case PositionTopLeft:
2635 moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
2637 case PositionBottomRight:
2638 moveResizeGeom = TQRect( orig.topLeft(), bottomright ) ;
2640 case PositionBottomLeft:
2641 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.y() ), TQPoint( orig.right(), bottomright.y()) ) ;
2643 case PositionTopRight:
2644 moveResizeGeom = TQRect( TQPoint( orig.x(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2650 moveResizeGeom = TQRect( TQPoint( orig.left(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2652 case PositionBottom:
2653 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), bottomright.y() ) ) ;
2656 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.top() ), TQPoint( orig.right(), bottomright.y()));
2659 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), bottomright.y() ) ) ;
2661 case PositionCenter:
2666 if (moveResizeGeom.size() != previousMoveResizeGeom.size())
2671 assert( mode == PositionCenter );
2673 moveResizeGeom.moveTopLeft( topleft );
2674 moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition(
this, moveResizeGeom.topLeft() ) );
2676 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
2677 moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 );
2679 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2680 moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge );
2681 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2682 moveResizeGeom.moveRight( desktopArea.left() + left_marge );
2683 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2684 moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
2685 if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
2693 bool active = isActiveBorderMaximizing();
2694 auto mode = active ? options->tilingMode
2695 : isResize() ? options->resizeMode : options->moveMode;
2697 if (rules()->checkMoveResizeMode(mode) == Options::Opaque)
2699 setGeometry(active ? activeBorderMaximizeGeometry() : moveResizeGeom);
2700 positionGeometryTip();
2702 else if (rules()->checkMoveResizeMode(mode) == Options::Transparent)
2710 positionGeometryTip();
2711 drawbound(active ? activeBorderMaximizeGeometry() : moveResizeGeom);
2715 workspace()->checkActiveBorder(globalPos, get_tqt_x_time());
2719 void Client::setActiveBorderMode( ActiveMaximizingMode mode )
2724 ActiveMaximizingMode Client::activeBorderMode()
const
2729 void Client::setActiveBorder(ActiveBorder border) {
2730 currentActiveBorder = border;
2733 ActiveBorder Client::activeBorder()
const {
2734 return currentActiveBorder;
2737 bool Client::isActiveBorderMaximizing()
const
2739 return activeMaximizing;
2742 void Client::setActiveBorderMaximizing(
bool maximizing )
2744 activeMaximizing = maximizing;
2745 bool opaque = rules()->checkMoveResizeMode(options->tilingMode) == Options::Opaque;
2747 if (maximizing || opaque) {
2751 if (maximizing && !opaque) {
2752 drawbound(activeBorderMaximizeGeometry());
2756 void Client::cancelActiveBorderMaximizing() {
2757 if (!activeMaximizing)
return;
2758 activeMaximizing =
false;
2761 if (rules()->checkMoveResizeMode(options->tilingMode) == Options::Transparent) {
2766 TQRect Client::activeBorderMaximizeGeometry()
2769 TQRect max = workspace()->clientArea(MaximizeArea, TQCursor::pos(), workspace()->currentDesktop());
2770 switch (activeBorderMode())
2772 case ActiveMaximizeMode:
2774 if (maximizeMode() == MaximizeFull)
2775 ret = geometryRestore();
2781 case ActiveTilingMode:
2783 switch (activeBorder())
2787 ret = TQRect( max.x(), max.y(), max.width()/2, max.height() );
2792 ret = TQRect( max.x() + max.width()/2, max.y(), max.width()/2, max.height() );
2797 ret = TQRect( max.x(), max.y(), max.width(), max.height()/2 );
2802 ret = TQRect( max.x(), max.y() + max.height()/2, max.width(), max.height()/2 );
2807 ret = TQRect( max.x(), max.y(), max.width()/2, max.height()/2 );
2810 case ActiveTopRight:
2812 ret = TQRect( max.x() + max.width()/2, max.y(), max.width()/2, max.height()/2 );
2815 case ActiveBottomLeft:
2817 ret = TQRect( max.x(), max.y() + max.height()/2, max.width()/2, max.height()/2 );
2820 case ActiveBottomRight:
2822 ret = TQRect( max.x() + max.width()/2, max.y() + max.height()/2, max.width()/2, max.height()/2);
2831 void Client::tileToBorder(ActiveBorder border) {
2834 setActiveBorderMode(ActiveTilingMode);
2835 setActiveBorder(border);
2836 TQRect geo = activeBorderMaximizeGeometry();
2837 if (geo.isValid() && !geo.isEmpty()) {
2840 workspace()->raiseClient(
this);
TQRect adjustedClientArea(const TQRect &desktop, const TQRect &area) const
void setGeometry(int x, int y, int w, int h, ForceGeometry_t force=NormalGeometrySet)
TQSize adjustedSize(const TQSize &, Sizemode mode=SizemodeAny) const
void setMaximize(bool vertically, bool horizontally)
void move(int x, int y, ForceGeometry_t force=NormalGeometrySet)