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 checkElectricBorders(
true );
58 void Workspace::kDestopResized()
61 TQRect geom = TDEApplication::desktop()->geometry();
62 NETSize desktop_geometry;
63 desktop_geometry.width = geom.width();
64 desktop_geometry.height = geom.height();
65 rootInfo->setDesktopGeometry( -1, desktop_geometry );
67 updateClientArea(
true );
68 checkElectricBorders(
true );
83 void Workspace::updateClientArea(
bool force )
85 TQDesktopWidget *desktopwidget = TDEApplication::desktop();
86 int nscreens = desktopwidget -> numScreens ();
88 TQRect* new_wareas =
new TQRect[ numberOfDesktops() + 1 ];
89 TQRect** new_sareas =
new TQRect*[ numberOfDesktops() + 1];
90 TQRect* screens =
new TQRect [ nscreens ];
91 TQRect desktopArea = desktopwidget -> geometry ();
96 screens [iS] = desktopwidget -> screenGeometry (iS);
99 i <= numberOfDesktops();
102 new_wareas[ i ] = desktopArea;
103 new_sareas[ i ] =
new TQRect [ nscreens ];
107 new_sareas[ i ][ iS ] = screens[ iS ];
109 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
111 if( !(*it)->hasStrut())
113 TQRect r = (*it)->adjustedClientArea( desktopArea, desktopArea );
114 if( (*it)->isOnAllDesktops())
116 i <= numberOfDesktops();
119 new_wareas[ i ] = new_wareas[ i ].intersect( r );
123 new_sareas[ i ][ iS ] =
124 new_sareas[ i ][ iS ].intersect(
125 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
130 new_wareas[ (*it)->desktop() ] = new_wareas[ (*it)->desktop() ].intersect( r );
136 new_sareas[ (*it)->desktop() ][ iS ] =
137 new_sareas[ (*it)->desktop() ][ iS ].intersect(
138 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
145 i <= numberOfDesktops();
151 kdDebug () <<
"new_sarea: " << new_sareas[ i ][ iS ] << endl;
155 if( topmenu_space != NULL )
157 TQRect topmenu_area = desktopArea;
158 topmenu_area.setTop( topMenuHeight());
160 i <= numberOfDesktops();
162 new_wareas[ i ] = new_wareas[ i ].intersect( topmenu_area );
165 bool changed = force;
171 !changed && i <= numberOfDesktops();
174 if( workarea[ i ] != new_wareas[ i ] )
179 if (new_sareas[ i ][ iS ] != screenarea [ i ][ iS ])
186 workarea = new_wareas;
189 screenarea = new_sareas;
192 for(
int i = 1; i <= numberOfDesktops(); i++)
194 r.pos.x = workarea[ i ].x();
195 r.pos.y = workarea[ i ].y();
196 r.size.width = workarea[ i ].width();
197 r.size.height = workarea[ i ].height();
198 rootInfo->setWorkArea( i, r );
201 updateTopMenuGeometry();
202 for( ClientList::ConstIterator it = clients.begin();
205 (*it)->checkWorkspacePosition();
206 for( ClientList::ConstIterator it = desktops.begin();
207 it != desktops.end();
209 (*it)->checkWorkspacePosition();
216 void Workspace::updateClientArea()
218 updateClientArea(
false );
229 TQRect Workspace::clientArea( clientAreaOption opt,
int screen,
int desktop )
const
231 if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
232 desktop = currentDesktop();
233 TQDesktopWidget *desktopwidget = kapp->desktop();
234 TQRect sarea = screenarea
235 ? screenarea[ desktop ][ screen ]
236 : desktopwidget->screenGeometry( screen );
237 TQRect warea = workarea[ desktop ].isNull()
238 ? kapp->desktop()->geometry()
239 : workarea[ desktop ];
243 if (options->xineramaMaximizeEnabled)
244 if (desktopwidget->numScreens() < 2)
250 case MaximizeFullArea:
251 if (options->xineramaMaximizeEnabled)
252 if (desktopwidget->numScreens() < 2)
253 return desktopwidget->geometry();
255 return desktopwidget->screenGeometry( screen );
257 return desktopwidget->geometry();
259 if (options->xineramaFullscreenEnabled)
260 if (desktopwidget->numScreens() < 2)
261 return desktopwidget->geometry();
263 return desktopwidget->screenGeometry( screen );
265 return desktopwidget->geometry();
267 if (options->xineramaPlacementEnabled)
268 if (desktopwidget->numScreens() < 2)
275 if (options->xineramaMovementEnabled)
276 if (desktopwidget->numScreens() < 2)
277 return desktopwidget->geometry();
279 return desktopwidget->screenGeometry( screen );
281 return desktopwidget->geometry();
285 return desktopwidget->geometry();
287 if (desktopwidget->numScreens() < 2)
288 return desktopwidget->geometry();
290 return desktopwidget->screenGeometry( screen );
296 TQRect Workspace::clientArea( clientAreaOption opt,
const TQPoint& p,
int desktop )
const
298 TQDesktopWidget *desktopwidget = TDEApplication::desktop();
299 int screen = desktopwidget->screenNumber( p );
301 screen = desktopwidget->primaryScreen();
302 return clientArea( opt, screen, desktop );
305 TQRect Workspace::clientArea( clientAreaOption opt,
const Client* c )
const
307 return clientArea( opt, c->geometry().center(), c->desktop());
316 TQPoint Workspace::adjustClientPosition( Client* c, TQPoint pos )
321 if (options->windowSnapZone || options->borderSnapZone )
323 const bool sOWO=options->snapOnlyWhenOverlapping;
324 const TQRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
325 const int xmin = maxRect.left();
326 const int xmax = maxRect.right()+1;
327 const int ymin = maxRect.top();
328 const int ymax = maxRect.bottom()+1;
330 const int cx(pos.x());
331 const int cy(pos.y());
332 const int cw(c->width());
333 const int ch(c->height());
341 int lx, ly, lrx, lry;
344 int snap = options->borderSnapZone;
347 if ((sOWO?(cx<xmin):
true) && (QABS(xmin-cx)<snap))
352 if ((sOWO?(rx>xmax):
true) && (QABS(rx-xmax)<snap) && (QABS(xmax-rx) < deltaX))
358 if ((sOWO?(cy<ymin):
true) && (QABS(ymin-cy)<snap))
363 if ((sOWO?(ry>ymax):
true) && (QABS(ry-ymax)<snap) && (QABS(ymax-ry) < deltaY))
371 snap = options->windowSnapZone;
374 TQValueList<Client *>::ConstIterator l;
375 for (l = clients.begin();l != clients.end();++l )
377 if ((*l)->isOnDesktop(currentDesktop()) &&
383 lrx = lx + (*l)->width();
384 lry = ly + (*l)->height();
386 if ( (( cy <= lry ) && ( cy >= ly )) ||
387 (( ry >= ly ) && ( ry <= lry )) ||
388 (( cy <= ly ) && ( ry >= lry )) )
390 if ((sOWO?(cx<lrx):
true) && (QABS(lrx-cx)<snap) && ( QABS(lrx -cx) < deltaX) )
392 deltaX = QABS( lrx - cx );
395 if ((sOWO?(rx>lx):
true) && (QABS(rx-lx)<snap) && ( QABS( rx - lx )<deltaX) )
397 deltaX = QABS(rx - lx);
402 if ( (( cx <= lrx ) && ( cx >= lx )) ||
403 (( rx >= lx ) && ( rx <= lrx )) ||
404 (( cx <= lx ) && ( rx >= lrx )) )
406 if ((sOWO?(cy<lry):
true) && (QABS(lry-cy)<snap) && (QABS( lry -cy ) < deltaY))
408 deltaY = QABS( lry - cy );
412 if ((sOWO?(ry>ly):
true) && (QABS(ry-ly)<snap) && (QABS( ry - ly ) < deltaY ))
414 deltaY = QABS( ry - ly );
421 pos = TQPoint(nx, ny);
426 TQRect Workspace::adjustClientSize( Client* c, TQRect moveResizeGeom,
int mode )
431 if ( options->windowSnapZone || options->borderSnapZone )
433 const bool sOWO=options->snapOnlyWhenOverlapping;
435 const TQRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop());
436 const int xmin = maxRect.left();
437 const int xmax = maxRect.right();
438 const int ymin = maxRect.top();
439 const int ymax = maxRect.bottom();
441 const int cx(moveResizeGeom.left());
442 const int cy(moveResizeGeom.top());
443 const int rx(moveResizeGeom.right());
444 const int ry(moveResizeGeom.bottom());
446 int newcx(cx), newcy(cy);
447 int newrx(rx), newry(ry);
451 int lx, ly, lrx, lry;
454 int snap = options->borderSnapZone;
460 #define SNAP_BORDER_TOP \
461 if ((sOWO?(newcy<ymin):true) && (QABS(ymin-newcy)<deltaY)) \
463 deltaY = QABS(ymin-newcy); \
467 #define SNAP_BORDER_BOTTOM \
468 if ((sOWO?(newry>ymax):true) && (QABS(ymax-newry)<deltaY)) \
470 deltaY = QABS(ymax-newcy); \
474 #define SNAP_BORDER_LEFT \
475 if ((sOWO?(newcx<xmin):true) && (QABS(xmin-newcx)<deltaX)) \
477 deltaX = QABS(xmin-newcx); \
481 #define SNAP_BORDER_RIGHT \
482 if ((sOWO?(newrx>xmax):true) && (QABS(xmax-newrx)<deltaX)) \
484 deltaX = QABS(xmax-newrx); \
489 case PositionBottomRight:
499 case PositionTopLeft:
509 case PositionTopRight:
513 case PositionBottomLeft:
526 snap = options->windowSnapZone;
531 TQValueList<Client *>::ConstIterator l;
532 for (l = clients.begin();l != clients.end();++l )
534 if ((*l)->isOnDesktop(currentDesktop()) &&
540 lrx =(*l)->x() + (*l)->width();
541 lry =(*l)->y() + (*l)->height();
543 #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
544 (( newry >= ly ) && ( newry <= lry )) || \
545 (( newcy <= ly ) && ( newry >= lry )) )
547 #define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
548 (( rx >= lx ) && ( rx <= lrx )) || \
549 (( cx <= lx ) && ( rx >= lrx )) )
551 #define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
553 && (QABS( lry - newcy ) < deltaY) ) { \
554 deltaY = QABS( lry - newcy ); \
558 #define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
560 && (QABS( ly - newry ) < deltaY) ) { \
561 deltaY = QABS( ly - newry ); \
565 #define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
567 && (QABS( lrx - newcx ) < deltaX)) { \
568 deltaX = QABS( lrx - newcx ); \
572 #define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
574 && (QABS( lx - newrx ) < deltaX)) \
576 deltaX = QABS( lx - newrx ); \
582 case PositionBottomRight:
592 case PositionTopLeft:
602 case PositionTopRight:
606 case PositionBottomLeft:
617 moveResizeGeom = TQRect(TQPoint(newcx, newcy), TQPoint(newrx, newry));
619 return moveResizeGeom;
625 void Workspace::setClientIsMoving( Client *c )
627 Q_ASSERT(!c || !movingClient);
639 void Workspace::cascadeDesktop()
642 Q_ASSERT( block_stacking_updates == 0 );
643 ClientList::ConstIterator it(stackingOrder().begin());
644 initPositioning->reinitCascading( currentDesktop());
645 TQRect area = clientArea( PlacementArea, TQPoint( 0, 0 ), currentDesktop());
646 for (; it != stackingOrder().end(); ++it)
648 if((!(*it)->isOnDesktop(currentDesktop())) ||
649 ((*it)->isMinimized()) ||
650 ((*it)->isOnAllDesktops()) ||
651 (!(*it)->isMovable()) )
653 initPositioning->placeCascaded(*it, area);
661 void Workspace::unclutterDesktop()
663 ClientList::Iterator it(clients.fromLast());
664 for (; it != clients.end(); --it)
666 if((!(*it)->isOnDesktop(currentDesktop())) ||
667 ((*it)->isMinimized()) ||
668 ((*it)->isOnAllDesktops()) ||
669 (!(*it)->isMovable()) )
671 initPositioning->placeSmart(*it, TQRect());
676 void Workspace::updateTopMenuGeometry( Client* c )
678 if( !managingTopMenus())
683 ev.xclient.display = tqt_xdisplay();
684 ev.xclient.type = ClientMessage;
685 ev.xclient.window = c->window();
686 static Atom msg_type_atom = XInternAtom( tqt_xdisplay(),
"_KDE_TOPMENU_MINSIZE", False );
687 ev.xclient.message_type = msg_type_atom;
688 ev.xclient.format = 32;
689 ev.xclient.data.l[0] = GET_QT_X_TIME();
690 ev.xclient.data.l[1] = topmenu_space->width();
691 ev.xclient.data.l[2] = topmenu_space->height();
692 ev.xclient.data.l[3] = 0;
693 ev.xclient.data.l[4] = 0;
694 XSendEvent( tqt_xdisplay(), c->window(), False, NoEventMask, &ev );
695 KWin::setStrut( c->window(), 0, 0, topmenu_height, 0 );
696 c->checkWorkspacePosition();
701 area = clientArea( MaximizeFullArea, TQPoint( 0, 0 ), 1 );
702 area.setHeight( topMenuHeight());
703 topmenu_space->setGeometry( area );
704 for( ClientList::ConstIterator it = topmenus.begin();
705 it != topmenus.end();
707 updateTopMenuGeometry( *it );
715 void Client::keepInArea( TQRect area,
bool partial )
720 area.setLeft( TQMIN( area.left() - width() + 100, area.left()));
721 area.setTop( TQMIN( area.top() - height() + 100, area.top()));
722 area.setRight( TQMAX( area.right() + width() - 100, area.right()));
723 area.setBottom( TQMAX( area.bottom() + height() - 100, area.bottom()));
725 if ( geometry().right() > area.right() && width() < area.width() )
726 move( area.right() - width(), y() );
727 if ( geometry().bottom() > area.bottom() && height() < area.height() )
728 move( x(), area.bottom() - height() );
729 if( !area.contains( geometry().topLeft() ))
754 NETExtendedStrut str = strut();
755 TQRect stareaL = TQRect(
759 str . left_end - str . left_start + 1 );
760 TQRect stareaR = TQRect (
761 desktopArea . right () - str . right_width + 1,
764 str . right_end - str . right_start + 1 );
765 TQRect stareaT = TQRect (
768 str . top_end - str . top_start + 1,
770 TQRect stareaB = TQRect (
772 desktopArea . bottom () - str . bottom_width + 1,
773 str . bottom_end - str . bottom_start + 1,
776 NETExtendedStrut ext = info->extendedStrut();
777 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
778 && ( str.left_width != 0 || str.right_width != 0 || str.top_width != 0 || str.bottom_width != 0 )) {
786 if (stareaT.top() == geometry().top() && stareaT.bottom() == geometry().bottom()) {
787 stareaT.setLeft(geometry().left());
788 stareaT.setRight(geometry().right());
791 if (stareaB.top() == geometry().top() && stareaB.bottom() == geometry().bottom()) {
792 stareaB.setLeft(geometry().left());
793 stareaB.setRight(geometry().right());
796 if (stareaL.left() == geometry().left() && stareaL.right() == geometry().right()) {
797 stareaL.setTop(geometry().top());
798 stareaL.setBottom(geometry().bottom());
801 if (stareaR.left() == geometry().left() && stareaR.right() == geometry().right()) {
802 stareaR.setTop(geometry().top());
803 stareaR.setBottom(geometry().bottom());
808 TQRect screenarea = workspace()->clientArea( ScreenArea,
this );
812 if( area == kapp->desktop()->geometry())
814 if( stareaL.left() < screenarea.left())
816 if( stareaR.right() > screenarea.right())
818 if( stareaT.top() < screenarea.top())
820 if( stareaB.bottom() < screenarea.bottom())
826 stareaL.setLeft( KMAX( stareaL.left(), screenarea.left()));
827 stareaR.setRight( KMIN( stareaR.right(), screenarea.right()));
828 stareaT.setTop( KMAX( stareaT.top(), screenarea.top()));
829 stareaB.setBottom( KMIN( stareaB.bottom(), screenarea.bottom()));
831 if (stareaL . intersects (area)) {
833 r . setLeft( stareaL . right() + 1 );
835 if (stareaR . intersects (area)) {
837 r . setRight( stareaR . left() - 1 );
839 if (stareaT . intersects (area)) {
841 r . setTop( stareaT . bottom() + 1 );
843 if (stareaB . intersects (area)) {
845 r . setBottom( stareaB . top() - 1 );
850 NETExtendedStrut Client::strut()
const
852 NETExtendedStrut ext = info->extendedStrut();
853 NETStrut str = info->strut();
854 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
855 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 ))
860 ext.left_width = str.left;
862 ext.left_end = XDisplayHeight( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
866 ext.right_width = str.right;
868 ext.right_end = XDisplayHeight( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
872 ext.top_width = str.top;
874 ext.top_end = XDisplayWidth( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
876 if( str.bottom != 0 )
878 ext.bottom_width = str.bottom;
879 ext.bottom_start = 0;
880 ext.bottom_end = XDisplayWidth( tqt_xdisplay(), DefaultScreen( tqt_xdisplay()));
886 bool Client::hasStrut()
const
888 NETExtendedStrut ext = strut();
889 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 )
896 void Client::updateWorkareaDiffs()
898 TQRect area = workspace()->clientArea( WorkArea,
this );
899 TQRect geom = geometry();
900 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
901 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
912 int Client::computeWorkareaDiff(
int left,
int right,
int a_left,
int a_right )
914 int left_diff = left - a_left;
915 int right_diff = a_right - right;
916 if( left_diff < 0 || right_diff < 0 )
921 int max_diff = ( a_right - a_left ) / 10;
922 if( left_diff < right_diff )
923 return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
924 else if( left_diff > right_diff )
925 return right_diff < max_diff ? right_diff + 1 : INT_MAX;
930 void Client::checkWorkspacePosition()
934 TQRect area = workspace()->clientArea( FullArea,
this );
935 if( geometry() != area )
941 TQRect area = workspace()->clientArea( FullScreenArea,
this );
942 if( geometry() != area )
950 if( workspace()->managingTopMenus())
953 ClientList mainclients = mainClients();
954 if( mainclients.count() == 1 )
955 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
957 area = workspace()->clientArea( MaximizeFullArea, TQPoint( 0, 0 ),
desktop());
958 area.setHeight( workspace()->topMenuHeight());
965 if( maximizeMode() != MaximizeRestore )
967 changeMaximize(
false,
false,
true );
971 int old_diff_x = workarea_diff_x;
972 int old_diff_y = workarea_diff_y;
973 updateWorkareaDiffs();
980 if( workspace()->initializing())
983 TQRect area = workspace()->clientArea( WorkArea,
this );
984 TQRect new_geom = geometry();
985 TQRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
986 TQRect tmp_area_x( area.left(), 0, area.width(), 0 );
987 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
989 TQRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
990 TQRect tmp_area_y( area.top(), 0, area.height(), 0 );
991 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
992 new_geom = TQRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
993 TQRect final_geom( new_geom.topLeft(),
adjustedSize( new_geom.size()));
994 if( final_geom != new_geom )
996 if( old_diff_x != INT_MAX && old_diff_x > 0 )
997 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
998 if( old_diff_y != INT_MAX && old_diff_y > 0 )
999 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
1001 if( final_geom != geometry() )
1017 void Client::checkDirection(
int new_diff,
int old_diff, TQRect& rect,
const TQRect& area )
1019 if( old_diff != INT_MIN )
1021 if( old_diff == INT_MAX )
1023 if( new_diff == INT_MIN )
1025 rect.setLeft( area.left());
1026 rect.setRight( area.right());
1033 rect.moveLeft( area.left() + ( -old_diff - 1 ));
1035 rect.moveRight( area.right() - ( old_diff - 1 ));
1040 rect.setLeft( area.left() + ( -old_diff - 1 ) );
1042 rect.setRight( area.right() - ( old_diff - 1 ));
1045 rect.setWidth( area.width());
1048 if( rect.left() < area.left())
1049 rect.moveLeft( area.left());
1050 else if( rect.right() > area.right())
1051 rect.moveRight( area.right());
1054 if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
1058 if( rect.left() < area.left() + 5 )
1059 rect.moveRight( area.left() + 5 );
1060 if( rect.right() > area.right() - 5 )
1061 rect.moveLeft( area.right() - 5 );
1064 if (!moveResizeMode && options->shadowEnabled(isActive()))
1069 drawIntersectingShadows();
1070 if (options->shadowEnabled(isActive()))
1071 drawDelayedShadow();
1078 TQSize Client::adjustedSize(
const TQSize& frame, Sizemode mode )
const
1082 TQSize wsize( frame.width() - ( border_left + border_right ),
1083 frame.height() - ( border_top + border_bottom ));
1084 if( wsize.isEmpty())
1085 wsize = TQSize( 1, 1 );
1087 return sizeForClientSize( wsize, mode,
false );
1092 TQSize Client::adjustedSize()
const
1094 return sizeForClientSize( clientSize());
1105 TQSize Client::sizeForClientSize(
const TQSize& wsize, Sizemode mode,
bool noframe )
const
1107 int w = wsize.width();
1108 int h = wsize.height();
1109 if( w < 1 || h < 1 )
1111 kdWarning() <<
"sizeForClientSize() with empty size!" << endl;
1112 kdWarning() << kdBacktrace() << endl;
1119 TQSize min_size = minSize();
1120 TQSize max_size = maxSize();
1121 if( decoration != NULL )
1123 TQSize decominsize = decoration->minimumSize();
1124 TQSize border_size( border_left + border_right, border_top + border_bottom );
1125 if( border_size.width() > decominsize.width())
1126 decominsize.setWidth( border_size.width());
1127 if( border_size.height() > decominsize.height())
1128 decominsize.setHeight( border_size.height());
1129 if( decominsize.width() > min_size.width())
1130 min_size.setWidth( decominsize.width());
1131 if( decominsize.height() > min_size.height())
1132 min_size.setHeight( decominsize.height());
1134 w = TQMIN( max_size.width(), w );
1135 h = TQMIN( max_size.height(), h );
1136 w = TQMAX( min_size.width(), w );
1137 h = TQMAX( min_size.height(), h );
1141 int width_inc = xSizeHint.width_inc;
1142 int height_inc = xSizeHint.height_inc;
1143 int basew_inc = xSizeHint.min_width;
1144 int baseh_inc = xSizeHint.min_height;
1145 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
1146 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
1162 if( xSizeHint.flags & PAspect )
1164 double min_aspect_w = xSizeHint.min_aspect.x;
1165 double min_aspect_h = xSizeHint.min_aspect.y;
1166 double max_aspect_w = xSizeHint.max_aspect.x;
1167 double max_aspect_h = xSizeHint.max_aspect.y;
1171 w -= xSizeHint.base_width;
1172 h -= xSizeHint.base_height;
1173 int max_width = max_size.width() - xSizeHint.base_width;
1174 int min_width = min_size.width() - xSizeHint.base_width;
1175 int max_height = max_size.height() - xSizeHint.base_height;
1176 int min_height = min_size.height() - xSizeHint.base_height;
1177 #define ASPECT_CHECK_GROW_W \
1178 if( min_aspect_w * h > min_aspect_h * w ) \
1180 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
1181 if( w + delta <= max_width ) \
1184 #define ASPECT_CHECK_SHRINK_H_GROW_W \
1185 if( min_aspect_w * h > min_aspect_h * w ) \
1187 int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
1188 if( h - delta >= min_height ) \
1192 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
1193 if( w + delta <= max_width ) \
1197 #define ASPECT_CHECK_GROW_H \
1198 if( max_aspect_w * h < max_aspect_h * w ) \
1200 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
1201 if( h + delta <= max_height ) \
1204 #define ASPECT_CHECK_SHRINK_W_GROW_H \
1205 if( max_aspect_w * h < max_aspect_h * w ) \
1207 int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
1208 if( w - delta >= min_width ) \
1212 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
1213 if( h + delta <= max_height ) \
1220 #if 0 // make SizemodeAny equal to SizemodeFixedW - prefer keeping fixed width,
1223 ASPECT_CHECK_SHRINK_H_GROW_W
1224 ASPECT_CHECK_SHRINK_W_GROW_H
1230 case SizemodeFixedW:
1234 ASPECT_CHECK_SHRINK_H_GROW_W
1235 ASPECT_CHECK_SHRINK_W_GROW_H
1239 case SizemodeFixedH:
1242 ASPECT_CHECK_SHRINK_W_GROW_H
1243 ASPECT_CHECK_SHRINK_H_GROW_W
1250 ASPECT_CHECK_SHRINK_H_GROW_W
1251 ASPECT_CHECK_SHRINK_W_GROW_H
1257 #undef ASPECT_CHECK_SHRINK_H_GROW_W
1258 #undef ASPECT_CHECK_SHRINK_W_GROW_H
1259 #undef ASPECT_CHECK_GROW_W
1260 #undef ASPECT_CHECK_GROW_H
1261 w += xSizeHint.base_width;
1262 h += xSizeHint.base_height;
1264 if( !rules()->checkStrictGeometry(
false ))
1267 if( maximizeMode() & MaximizeHorizontal )
1269 if( maximizeMode() & MaximizeVertical )
1275 w += border_left + border_right;
1276 h += border_top + border_bottom;
1278 return rules()->checkSize( TQSize( w, h ));
1284 void Client::getWmNormalHints()
1287 if (XGetWMNormalHints(tqt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
1288 xSizeHint.flags = 0;
1291 if( ! ( xSizeHint.flags & PMinSize ))
1292 xSizeHint.min_width = xSizeHint.min_height = 0;
1293 if( xSizeHint.flags & PBaseSize )
1298 if( ! ( xSizeHint.flags & PMinSize ))
1300 xSizeHint.min_width = xSizeHint.base_width;
1301 xSizeHint.min_height = xSizeHint.base_height;
1305 xSizeHint.base_width = xSizeHint.base_height = 0;
1306 if( ! ( xSizeHint.flags & PMaxSize ))
1307 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
1310 xSizeHint.max_width = TQMAX( xSizeHint.max_width, 1 );
1311 xSizeHint.max_height = TQMAX( xSizeHint.max_height, 1 );
1313 if( xSizeHint.flags & PResizeInc )
1315 xSizeHint.width_inc = kMax( xSizeHint.width_inc, 1 );
1316 xSizeHint.height_inc = kMax( xSizeHint.height_inc, 1 );
1320 xSizeHint.width_inc = 1;
1321 xSizeHint.height_inc = 1;
1323 if( xSizeHint.flags & PAspect )
1325 xSizeHint.min_aspect.y = kMax( xSizeHint.min_aspect.y, 1 );
1326 xSizeHint.max_aspect.y = kMax( xSizeHint.max_aspect.y, 1 );
1330 xSizeHint.min_aspect.x = 1;
1331 xSizeHint.min_aspect.y = INT_MAX;
1332 xSizeHint.max_aspect.x = INT_MAX;
1333 xSizeHint.max_aspect.y = 1;
1335 if( ! ( xSizeHint.flags & PWinGravity ))
1336 xSizeHint.win_gravity = NorthWestGravity;
1340 if( new_size != size() && !isFullScreen())
1342 TQRect orig_geometry = geometry();
1343 resizeWithChecks( new_size );
1344 if( ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
1348 TQRect area = workspace()->clientArea( MovementArea,
this );
1349 if( area.contains( orig_geometry ))
1351 area = workspace()->clientArea( WorkArea,
this );
1352 if( area.contains( orig_geometry ))
1357 updateAllowedActions();
1360 TQSize Client::minSize()
const
1362 return rules()->checkMinSize( TQSize( xSizeHint.min_width, xSizeHint.min_height ));
1365 TQSize Client::maxSize()
const
1367 return rules()->checkMaxSize( TQSize( xSizeHint.max_width, xSizeHint.max_height ));
1375 void Client::sendSyntheticConfigureNotify()
1378 c.type = ConfigureNotify;
1379 c.send_event = True;
1381 c.window = window();
1382 c.x = x() + clientPos().x();
1383 c.y = y() + clientPos().y();
1384 c.width = clientSize().width();
1385 c.height = clientSize().height();
1388 c.override_redirect = 0;
1389 XSendEvent( tqt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
1392 const TQPoint Client::calculateGravitation(
bool invert,
int gravity )
const
1398 gravity = xSizeHint.win_gravity;
1403 case NorthWestGravity:
1412 case NorthEastGravity:
1430 case SouthWestGravity:
1432 dy = -border_bottom;
1436 dy = -border_bottom;
1438 case SouthEastGravity:
1440 dy = -border_bottom;
1443 if( gravity != CenterGravity )
1450 dx = - ( border_left + border_right ) / 2;
1451 dy = - ( border_top + border_bottom ) / 2;
1454 return TQPoint( x() + dx, y() + dy );
1456 return TQPoint( x() - dx, y() - dy );
1459 void Client::configureRequest(
int value_mask,
int rx,
int ry,
int rw,
int rh,
int gravity,
bool from_tool )
1462 gravity = xSizeHint.win_gravity;
1463 if( value_mask & ( CWX | CWY ))
1465 TQPoint new_pos = calculateGravitation(
true, gravity );
1466 if ( value_mask & CWX )
1468 if ( value_mask & CWY )
1475 if ( new_pos.x() == x() + clientPos().x() && new_pos.y() == y() + clientPos().y()
1476 && gravity == NorthWestGravity && !from_tool )
1482 int nw = clientSize().width();
1483 int nh = clientSize().height();
1484 if ( value_mask & CWWidth )
1486 if ( value_mask & CWHeight )
1488 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
1489 new_pos = rules()->checkPosition( new_pos );
1492 if ( maximizeMode() != MaximizeFull
1495 TQRect orig_geometry = geometry();
1496 GeometryUpdatesPostponer blocker(
this );
1499 setGeometry( TQRect( calculateGravitation(
false, gravity ), size()));
1500 updateFullScreenHack( TQRect( new_pos, TQSize( nw, nh )));
1501 TQRect area = workspace()->clientArea( WorkArea,
this );
1502 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
1503 && area.contains( orig_geometry ))
1511 workspace() -> updateClientArea ();
1515 if ( value_mask & (CWWidth | CWHeight )
1516 && ! ( value_mask & ( CWX | CWY )) )
1518 int nw = clientSize().width();
1519 int nh = clientSize().height();
1520 if ( value_mask & CWWidth )
1522 if ( value_mask & CWHeight )
1524 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
1528 TQRect orig_geometry = geometry();
1529 GeometryUpdatesPostponer blocker(
this );
1530 int save_gravity = xSizeHint.win_gravity;
1531 xSizeHint.win_gravity = gravity;
1532 resizeWithChecks( ns );
1533 xSizeHint.win_gravity = save_gravity;
1534 updateFullScreenHack( TQRect( calculateGravitation(
true, xSizeHint.win_gravity ), TQSize( nw, nh )));
1535 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
1539 TQRect area = workspace()->clientArea( MovementArea,
this );
1540 if( area.contains( orig_geometry ))
1542 area = workspace()->clientArea( WorkArea,
this );
1543 if( area.contains( orig_geometry ))
1553 void Client::resizeWithChecks(
int w,
int h, ForceGeometry_t force )
1555 if( shade_geometry_change )
1559 if( h == border_top + border_bottom )
1561 kdWarning() <<
"Shaded geometry passed for size:" << endl;
1562 kdWarning() << kdBacktrace() << endl;
1567 TQRect area = workspace()->clientArea( WorkArea,
this );
1569 if( w > area.width())
1571 if( h > area.height())
1576 switch( xSizeHint.win_gravity )
1578 case NorthWestGravity:
1582 newx = ( newx + width() / 2 ) - ( w / 2 );
1584 case NorthEastGravity:
1585 newx = newx + width() - w;
1588 newy = ( newy + height() / 2 ) - ( h / 2 );
1591 newx = ( newx + width() / 2 ) - ( w / 2 );
1592 newy = ( newy + height() / 2 ) - ( h / 2 );
1598 newx = newx + width() - w;
1599 newy = ( newy + height() / 2 ) - ( h / 2 );
1601 case SouthWestGravity:
1602 newy = newy + height() - h;
1605 newx = ( newx + width() / 2 ) - ( w / 2 );
1606 newy = newy + height() - h;
1608 case SouthEastGravity:
1609 newx = newx + width() - w;
1610 newy = newy + height() - h;
1615 if( workarea_diff_x != INT_MIN && w <= area.width())
1617 if( newx < area.left())
1619 if( newx + w > area.right() + 1 )
1620 newx = area.right() + 1 - w;
1621 assert( newx >= area.left() && newx + w <= area.right() + 1 );
1623 if( workarea_diff_y != INT_MIN && h <= area.height())
1625 if( newy < area.top())
1627 if( newy + h > area.bottom() + 1 )
1628 newy = area.bottom() + 1 - h;
1629 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
1635 void Client::NETMoveResizeWindow(
int flags,
int x,
int y,
int width,
int height )
1637 int gravity = flags & 0xff;
1639 if( flags & ( 1 << 8 ))
1641 if( flags & ( 1 << 9 ))
1643 if( flags & ( 1 << 10 ))
1644 value_mask |= CWWidth;
1645 if( flags & ( 1 << 11 ))
1646 value_mask |= CWHeight;
1647 configureRequest( value_mask, x, y, width, height, gravity,
true );
1656 if( !motif_may_move || isFullScreen())
1658 if( isSpecialWindow() && !isSplash() && !isToolbar())
1660 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
1662 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
1672 if( !motif_may_resize || isFullScreen())
1674 if( isSpecialWindow() )
1676 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
1678 if( rules()->checkSize( TQSize()).isValid())
1681 TQSize min = minSize();
1682 TQSize max = maxSize();
1683 return min.width() < max.width() || min.height() < max.height();
1689 bool Client::isMaximizable()
const
1691 if( isModalSystemNotification())
1695 TemporaryAssign< MaximizeMode > tmp( max_mode, MaximizeRestore );
1699 if ( maximizeMode() != MaximizeRestore )
1701 TQSize max = maxSize();
1703 if( max.width() < 32767 || max.height() < 32767 )
1708 TQSize areasize = workspace()->clientArea( MaximizeArea,
this ).size();
1709 if( max.width() < areasize.width() || max.height() < areasize.height())
1732 if( shade_geometry_change )
1736 if( h == border_top + border_bottom )
1738 kdDebug() <<
"Shaded geometry passed for size:" << endl;
1739 kdDebug() << kdBacktrace() << endl;
1743 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1744 h = border_top + border_bottom;
1749 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1751 if( force == NormalGeometrySet && frame_geometry == TQRect( x, y, w, h ))
1753 frame_geometry = TQRect( x, y, w, h );
1754 updateWorkareaDiffs();
1755 if( postpone_geometry_updates != 0 )
1757 pending_geometry_update =
true;
1760 resizeDecoration( TQSize( w, h ));
1761 XMoveResizeWindow( tqt_xdisplay(), frameId(), x, y, w, h );
1765 TQSize cs = clientSize();
1766 XMoveResizeWindow( tqt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
1767 cs.width(), cs.height());
1768 XMoveResizeWindow( tqt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
1772 updateWorkareaDiffs();
1773 sendSyntheticConfigureNotify();
1774 updateWindowRules();
1775 checkMaximizeGeometry();
1776 workspace()->checkActiveScreen(
this );
1779 void Client::plainResize(
int w,
int h, ForceGeometry_t force )
1782 if( shade_geometry_change )
1786 if( h == border_top + border_bottom )
1788 kdDebug() <<
"Shaded geometry passed for size:" << endl;
1789 kdDebug() << kdBacktrace() << endl;
1793 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1794 h = border_top + border_bottom;
1799 client_size = TQSize( w - border_left - border_right, h - border_top - border_bottom );
1801 if( TQSize( w, h ) != rules()->checkSize( TQSize( w, h )))
1803 kdDebug() <<
"forced size fail:" << TQSize( w,h ) <<
":" << rules()->checkSize( TQSize( w, h )) << endl;
1804 kdDebug() << kdBacktrace() << endl;
1806 if( force == NormalGeometrySet && frame_geometry.size() == TQSize( w, h ))
1808 frame_geometry.setSize( TQSize( w, h ));
1809 updateWorkareaDiffs();
1810 if( postpone_geometry_updates != 0 )
1812 pending_geometry_update =
true;
1815 resizeDecoration( TQSize( w, h ));
1816 XResizeWindow( tqt_xdisplay(), frameId(), w, h );
1820 TQSize cs = clientSize();
1821 XMoveResizeWindow( tqt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
1822 cs.width(), cs.height());
1823 XMoveResizeWindow( tqt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
1826 updateWorkareaDiffs();
1827 sendSyntheticConfigureNotify();
1828 updateWindowRules();
1829 checkMaximizeGeometry();
1830 workspace()->checkActiveScreen(
this );
1838 if( force == NormalGeometrySet && frame_geometry.topLeft() == TQPoint( x, y ))
1840 frame_geometry.moveTopLeft( TQPoint( x, y ));
1841 updateWorkareaDiffs();
1842 if( postpone_geometry_updates != 0 )
1844 pending_geometry_update =
true;
1847 XMoveWindow( tqt_xdisplay(), frameId(), x, y );
1848 sendSyntheticConfigureNotify();
1849 updateWindowRules();
1850 checkMaximizeGeometry();
1851 workspace()->checkActiveScreen(
this );
1855 void Client::postponeGeometryUpdates(
bool postpone )
1859 if( postpone_geometry_updates == 0 )
1860 pending_geometry_update =
false;
1861 ++postpone_geometry_updates;
1865 if( --postpone_geometry_updates == 0 )
1867 if( pending_geometry_update )
1870 setGeometry( TQRect( pos(), adjustedSize()), ForceGeometrySet );
1873 pending_geometry_update =
false;
1879 void Client::maximize( MaximizeMode m )
1881 setMaximize( m & MaximizeVertical, m & MaximizeHorizontal );
1890 max_mode & MaximizeVertical ? !vertically : vertically,
1891 max_mode & MaximizeHorizontal ? !horizontally : horizontally,
1895 void Client::changeMaximize(
bool vertical,
bool horizontal,
bool adjust )
1897 if( !isMaximizable())
1900 MaximizeMode old_mode = max_mode;
1905 max_mode = MaximizeMode( max_mode ^ MaximizeVertical );
1907 max_mode = MaximizeMode( max_mode ^ MaximizeHorizontal );
1910 max_mode = rules()->checkMaximize( max_mode );
1911 if( !adjust && max_mode == old_mode )
1914 GeometryUpdatesPostponer blocker(
this );
1917 Q_ASSERT( !( vertical && horizontal )
1918 || ((( max_mode & MaximizeVertical ) != 0 ) == (( max_mode & MaximizeHorizontal ) != 0 )));
1920 TQRect clientArea = workspace()->clientArea( MaximizeArea,
this );
1923 if( !adjust && !( y() == clientArea.top() && height() == clientArea.height()))
1925 geom_restore.setTop( y());
1926 geom_restore.setHeight( height());
1928 if( !adjust && !( x() == clientArea.left() && width() == clientArea.width()))
1930 geom_restore.setLeft( x());
1931 geom_restore.setWidth( width());
1936 if(( vertical && !(old_mode & MaximizeVertical ))
1937 || ( horizontal && !( old_mode & MaximizeHorizontal )))
1938 Notify::raise( Notify::Maximize );
1940 Notify::raise( Notify::UnMaximize );
1943 if( decoration != NULL )
1944 decoration->borders( border_left, border_right, border_top, border_bottom );
1947 if ( old_mode==MaximizeFull && max_mode==MaximizeRestore )
1949 if ( maximizeModeRestore()==MaximizeVertical )
1951 max_mode = MaximizeVertical;
1952 maxmode_restore = MaximizeRestore;
1954 if ( maximizeModeRestore()==MaximizeHorizontal )
1956 max_mode = MaximizeHorizontal;
1957 maxmode_restore = MaximizeRestore;
1964 case MaximizeVertical:
1966 if( old_mode & MaximizeHorizontal )
1968 if( geom_restore.width() == 0 )
1970 plainResize(
adjustedSize(TQSize(width(), clientArea.height()), SizemodeFixedH ));
1971 workspace()->placeSmart(
this, clientArea );
1974 setGeometry( TQRect(TQPoint( geom_restore.x(), clientArea.top()),
1975 adjustedSize(TQSize( geom_restore.width(), clientArea.height()), SizemodeFixedH )), ForceGeometrySet);
1978 setGeometry( TQRect(TQPoint(x(), clientArea.top()),
1979 adjustedSize(TQSize(width(), clientArea.height()), SizemodeFixedH )), ForceGeometrySet);
1980 info->setState( NET::MaxVert, NET::Max );
1984 case MaximizeHorizontal:
1986 if( old_mode & MaximizeVertical )
1988 if( geom_restore.height() == 0 )
1990 plainResize(
adjustedSize(TQSize(clientArea.width(), height()), SizemodeFixedW ));
1991 workspace()->placeSmart(
this, clientArea );
1994 setGeometry( TQRect( TQPoint(clientArea.left(), geom_restore.y()),
1995 adjustedSize(TQSize(clientArea.width(), geom_restore.height()), SizemodeFixedW )), ForceGeometrySet);
1998 setGeometry( TQRect( TQPoint(clientArea.left(), y()),
1999 adjustedSize(TQSize(clientArea.width(), height()), SizemodeFixedW )), ForceGeometrySet);
2000 info->setState( NET::MaxHoriz, NET::Max );
2004 case MaximizeRestore:
2006 TQRect restore = geometry();
2008 if( old_mode & MaximizeVertical )
2010 restore.setTop( geom_restore.top());
2011 restore.setBottom( geom_restore.bottom());
2013 if( old_mode & MaximizeHorizontal )
2015 restore.setLeft( geom_restore.left());
2016 restore.setRight( geom_restore.right());
2018 if( !restore.isValid())
2020 TQSize s = TQSize( clientArea.width()*2/3, clientArea.height()*2/3 );
2021 if( geom_restore.width() > 0 )
2022 s.setWidth( geom_restore.width());
2023 if( geom_restore.height() > 0 )
2024 s.setHeight( geom_restore.height());
2026 workspace()->placeSmart(
this, clientArea );
2027 restore = geometry();
2028 if( geom_restore.width() > 0 )
2029 restore.moveLeft( geom_restore.x());
2030 if( geom_restore.height() > 0 )
2031 restore.moveTop( geom_restore.y());
2034 info->setState( 0, NET::Max );
2042 if( old_mode & MaximizeVertical )
2043 maxmode_restore = MaximizeVertical;
2044 if( old_mode & MaximizeHorizontal )
2045 maxmode_restore = MaximizeHorizontal;
2047 TQSize adjSize =
adjustedSize(clientArea.size(), SizemodeMax );
2048 TQRect r = TQRect(clientArea.topLeft(), adjSize);
2050 info->setState( NET::Max, NET::Max );
2057 updateAllowedActions();
2058 if( decoration != NULL )
2059 decoration->maximizeChange();
2060 updateWindowRules();
2063 void Client::resetMaximize()
2065 if( max_mode == MaximizeRestore )
2067 max_mode = MaximizeRestore;
2068 Notify::raise( Notify::UnMaximize );
2069 info->setState( 0, NET::Max );
2070 updateAllowedActions();
2071 if( decoration != NULL )
2072 decoration->borders( border_left, border_right, border_top, border_bottom );
2074 setGeometry( TQRect( pos(), sizeForClientSize( clientSize())), ForceGeometrySet );
2077 if( decoration != NULL )
2078 decoration->maximizeChange();
2081 void Client::checkMaximizeGeometry()
2087 if( isMove() || isResize())
2090 static int recursion_protection = 0;
2091 if( recursion_protection > 3 )
2093 kdWarning( 1212 ) <<
"Check maximize overflow - you loose!" << endl;
2094 kdWarning( 1212 ) << kdBacktrace() << endl;
2097 ++recursion_protection;
2098 TQRect max_area = workspace()->clientArea( MaximizeArea,
this );
2099 if( geometry() == max_area )
2101 if( max_mode != MaximizeFull )
2102 maximize( MaximizeFull );
2104 else if( x() == max_area.left() && width() == max_area.width())
2106 if( max_mode != MaximizeHorizontal )
2107 maximize( MaximizeHorizontal );
2109 else if( y() == max_area.top() && height() == max_area.height())
2111 if( max_mode != MaximizeVertical )
2112 maximize( MaximizeVertical );
2114 else if( max_mode != MaximizeRestore )
2118 --recursion_protection;
2121 bool Client::isFullScreenable(
bool fullscreen_hack )
const
2123 if( !rules()->checkFullScreen(
true ))
2125 if( fullscreen_hack )
2126 return isNormalWindow();
2127 if( rules()->checkStrictGeometry(
false ))
2130 TQRect fsarea = workspace()->clientArea( FullScreenArea,
this );
2131 if( sizeForClientSize( fsarea.size(), SizemodeAny, true ) != fsarea.size())
2135 return !isSpecialWindow();
2138 bool Client::userCanSetFullScreen()
const
2140 if( fullscreen_mode == FullScreenHack )
2142 if( !isFullScreenable(
false ))
2145 TemporaryAssign< FullScreenMode > tmp( fullscreen_mode, FullScreenNone );
2146 return isNormalWindow() && isMaximizable();
2149 void Client::setFullScreen(
bool set,
bool user )
2151 if( !isFullScreen() && !
set )
2153 if( fullscreen_mode == FullScreenHack )
2155 if( user && !userCanSetFullScreen())
2157 set = rules()->checkFullScreen(
set );
2158 setShade( ShadeNone );
2159 bool was_fs = isFullScreen();
2161 geom_fs_restore = geometry();
2162 fullscreen_mode =
set ? FullScreenNormal : FullScreenNone;
2163 if( was_fs == isFullScreen())
2165 StackingUpdatesBlocker blocker1( workspace());
2166 GeometryUpdatesPostponer blocker2(
this );
2167 workspace()->updateClientLayer(
this );
2168 info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
2169 updateDecoration(
false,
false );
2171 setGeometry( workspace()->clientArea( FullScreenArea,
this ));
2174 if( !geom_fs_restore.isNull())
2179 setGeometry( workspace()->clientArea( MaximizeArea,
this ));
2182 updateWindowRules();
2185 int Client::checkFullScreenHack(
const TQRect& geom )
const
2188 if( noBorder() && !isUserNoBorder() && isFullScreenable(
true ))
2190 if( geom.size() == workspace()->clientArea( FullArea, geom.center(),
desktop()).size())
2192 if( geom.size() == workspace()->clientArea( ScreenArea, geom.center(),
desktop()).size())
2198 void Client::updateFullScreenHack(
const TQRect& geom )
2200 int type = checkFullScreenHack( geom );
2201 if( fullscreen_mode == FullScreenNone && type != 0 )
2203 fullscreen_mode = FullScreenHack;
2204 updateDecoration(
false,
false );
2206 if( rules()->checkStrictGeometry(
false ))
2209 ? workspace()->clientArea( FullArea, geom.center(),
desktop())
2210 : workspace()->clientArea( ScreenArea, geom.center(),
desktop());
2213 geom = workspace()->clientArea( FullScreenArea, geom.center(),
desktop());
2216 else if( fullscreen_mode == FullScreenHack && type == 0 )
2218 fullscreen_mode = FullScreenNone;
2219 updateDecoration(
false,
false );
2222 StackingUpdatesBlocker blocker( workspace());
2223 workspace()->updateClientLayer(
this );
2226 static TQRect* visible_bound = 0;
2227 static GeometryTip* geometryTip = 0;
2229 void Client::drawbound(
const TQRect& geom )
2231 assert( visible_bound == NULL );
2232 visible_bound =
new TQRect( geom );
2233 doDrawbound( *visible_bound,
false );
2236 void Client::clearbound()
2238 if( visible_bound == NULL )
2240 doDrawbound( *visible_bound,
true );
2241 delete visible_bound;
2245 void Client::doDrawbound(
const TQRect& geom,
bool clear )
2247 if( decoration != NULL && decoration->drawbound( geom, clear ))
2249 TQPainter p ( workspace()->desktopWidget() );
2250 p.setPen( TQPen( Qt::white, 5 ) );
2251 p.setRasterOp( TQt::XorROP );
2257 g.setLeft( g.left() + 2 );
2258 g.setRight( g.right() - 2 );
2260 if( g.height() > 5 )
2262 g.setTop( g.top() + 2 );
2263 g.setBottom( g.bottom() - 2 );
2268 void Client::positionGeometryTip()
2270 assert( isMove() || isResize());
2272 if (options->showGeometryTip())
2276 bool save_under = ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2277 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque );
2278 geometryTip =
new GeometryTip( &xSizeHint, save_under );
2280 TQRect wgeom( moveResizeGeom );
2281 wgeom.setWidth( wgeom.width() - ( width() - clientSize().width()));
2282 wgeom.setHeight( wgeom.height() - ( height() - clientSize().height()));
2284 wgeom.setHeight( 0 );
2285 geometryTip->setGeometry( wgeom );
2286 if( !geometryTip->isVisible())
2288 geometryTip->show();
2289 geometryTip->raise();
2294 class EatAllPaintEvents
2298 virtual bool eventFilter( TQObject* o, TQEvent* e )
2299 {
return e->type() == TQEvent::Paint && TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(geometryTip); }
2302 static EatAllPaintEvents* eater = 0;
2304 bool Client::startMoveResize()
2306 assert( !moveResizeMode );
2307 assert( TQWidget::keyboardGrabber() == NULL );
2308 assert( TQWidget::mouseGrabber() == NULL );
2309 if( TQApplication::activePopupWidget() != NULL )
2311 bool has_grab =
false;
2315 XSetWindowAttributes attrs;
2316 TQRect r = workspace()->clientArea( FullArea,
this );
2317 move_resize_grab_window = XCreateWindow( tqt_xdisplay(), workspace()->rootWin(), r.x(), r.y(),
2318 r.width(), r.height(), 0, CopyFromParent, InputOnly, CopyFromParent, 0, &attrs );
2319 XMapRaised( tqt_xdisplay(), move_resize_grab_window );
2320 if( XGrabPointer( tqt_xdisplay(), move_resize_grab_window, False,
2321 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
2322 GrabModeAsync, GrabModeAsync, move_resize_grab_window, cursor.handle(), GET_QT_X_TIME() ) == Success )
2324 if( XGrabKeyboard( tqt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, GET_QT_X_TIME() ) == Success )
2328 XDestroyWindow( tqt_xdisplay(), move_resize_grab_window );
2329 move_resize_grab_window = None;
2332 if ( maximizeMode() != MaximizeRestore )
2335 moveResizeMode =
true;
2336 workspace()->setClientIsMoving(
this);
2337 initialMoveResizeGeom = moveResizeGeom = geometry();
2338 checkUnrestrictedMoveResize();
2340 if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove))
2342 if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque){
2343 savedOpacity_ = opacity_;
2344 setOpacity(options->translucentMovingWindows, options->movingWindowOpacity);
2346 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2347 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
2350 kapp->sendPostedEvents();
2356 eater =
new EatAllPaintEvents;
2359 Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
2363 void Client::finishMoveResize(
bool cancel )
2370 checkMaximizeGeometry();
2372 Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
2375 void Client::leaveMoveResize()
2378 if (rules()->checkMoveResizeMode( options->moveMode ) == Options::Opaque)
2379 setOpacity(
true, savedOpacity_);
2380 if ((isResize() && options->removeShadowsOnResize) || (isMove() && options->removeShadowsOnMove))
2385 geometryTip->hide();
2389 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
2390 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
2392 XUngrabKeyboard( tqt_xdisplay(), GET_QT_X_TIME() );
2393 XUngrabPointer( tqt_xdisplay(), GET_QT_X_TIME() );
2394 XDestroyWindow( tqt_xdisplay(), move_resize_grab_window );
2395 move_resize_grab_window = None;
2396 workspace()->setClientIsMoving(0);
2397 if( move_faked_activity )
2398 workspace()->unfakeActivity(
this );
2399 move_faked_activity =
false;
2400 moveResizeMode =
false;
2403 if (options->shadowEnabled(isActive()))
2405 drawIntersectingShadows();
2406 updateOpacityCache();
2414 void Client::checkUnrestrictedMoveResize()
2416 if( unrestrictedMoveResize )
2418 TQRect desktopArea = workspace()->clientArea( WorkArea, moveResizeGeom.center(),
desktop());
2419 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
2422 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
2423 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
2425 titlebar_marge = initialMoveResizeGeom.height();
2426 top_marge = border_bottom;
2427 bottom_marge = border_top;
2430 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
2431 unrestrictedMoveResize =
true;
2432 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2433 unrestrictedMoveResize =
true;
2434 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2435 unrestrictedMoveResize =
true;
2436 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2437 unrestrictedMoveResize =
true;
2438 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
2439 unrestrictedMoveResize =
true;
2443 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
2444 unrestrictedMoveResize =
true;
2446 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2447 unrestrictedMoveResize =
true;
2448 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2449 unrestrictedMoveResize =
true;
2450 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2451 unrestrictedMoveResize =
true;
2455 void Client::handleMoveResize(
int x,
int y,
int x_root,
int y_root )
2457 if(( mode == PositionCenter && !
isMovable())
2458 || ( mode != PositionCenter && ( isShade() || !
isResizable())))
2461 if ( !moveResizeMode )
2463 TQPoint p( TQPoint( x, y ) - moveOffset );
2464 if (p.manhattanLength() >= 6)
2466 if( !startMoveResize())
2478 if ( mode != PositionCenter && shade_mode != ShadeNone )
2479 setShade( ShadeNone );
2481 TQPoint globalPos( x_root, y_root );
2484 TQPoint topleft = globalPos - moveOffset;
2485 TQPoint bottomright = globalPos + invertedMoveOffset;
2486 TQRect previousMoveResizeGeom = moveResizeGeom;
2492 TQRect desktopArea = workspace()->clientArea( WorkArea, globalPos,
desktop());
2493 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
2494 if( unrestrictedMoveResize )
2495 left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
2499 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
2500 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
2502 titlebar_marge = initialMoveResizeGeom.height();
2503 top_marge = border_bottom;
2504 bottom_marge = border_top;
2507 bool update =
false;
2511 TQRect orig = initialMoveResizeGeom;
2512 Sizemode sizemode = SizemodeAny;
2515 case PositionTopLeft:
2516 moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
2518 case PositionBottomRight:
2519 moveResizeGeom = TQRect( orig.topLeft(), bottomright ) ;
2521 case PositionBottomLeft:
2522 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.y() ), TQPoint( orig.right(), bottomright.y()) ) ;
2524 case PositionTopRight:
2525 moveResizeGeom = TQRect( TQPoint( orig.x(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2528 moveResizeGeom = TQRect( TQPoint( orig.left(), topleft.y() ), orig.bottomRight() ) ;
2529 sizemode = SizemodeFixedH;
2531 case PositionBottom:
2532 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( orig.right(), bottomright.y() ) ) ;
2533 sizemode = SizemodeFixedH;
2536 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.top() ), orig.bottomRight() ) ;
2537 sizemode = SizemodeFixedW;
2540 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), orig.bottom() ) ) ;
2541 sizemode = SizemodeFixedW;
2543 case PositionCenter:
2550 moveResizeGeom = workspace()->adjustClientSize(
this, moveResizeGeom, mode );
2553 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
2554 moveResizeGeom.setBottom( desktopArea.top() + top_marge );
2555 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2556 moveResizeGeom.setTop( desktopArea.bottom() - bottom_marge );
2557 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2558 moveResizeGeom.setRight( desktopArea.left() + left_marge );
2559 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2560 moveResizeGeom.setLeft(desktopArea.right() - right_marge );
2561 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
2562 moveResizeGeom.setTop( desktopArea.top());
2564 TQSize size =
adjustedSize( moveResizeGeom.size(), sizemode );
2566 topleft = TQPoint( moveResizeGeom.right() - size.width() + 1, moveResizeGeom.bottom() - size.height() + 1 );
2567 bottomright = TQPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
2568 orig = moveResizeGeom;
2571 case PositionTopLeft:
2572 moveResizeGeom = TQRect( topleft, orig.bottomRight() ) ;
2574 case PositionBottomRight:
2575 moveResizeGeom = TQRect( orig.topLeft(), bottomright ) ;
2577 case PositionBottomLeft:
2578 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.y() ), TQPoint( orig.right(), bottomright.y()) ) ;
2580 case PositionTopRight:
2581 moveResizeGeom = TQRect( TQPoint( orig.x(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2587 moveResizeGeom = TQRect( TQPoint( orig.left(), topleft.y() ), TQPoint( bottomright.x(), orig.bottom()) ) ;
2589 case PositionBottom:
2590 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), bottomright.y() ) ) ;
2593 moveResizeGeom = TQRect( TQPoint( topleft.x(), orig.top() ), TQPoint( orig.right(), bottomright.y()));
2596 moveResizeGeom = TQRect( orig.topLeft(), TQPoint( bottomright.x(), bottomright.y() ) ) ;
2598 case PositionCenter:
2603 if( moveResizeGeom.size() != previousMoveResizeGeom.size())
2608 assert( mode == PositionCenter );
2610 moveResizeGeom.moveTopLeft( topleft );
2611 moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition(
this, moveResizeGeom.topLeft() ) );
2613 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
2614 moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 );
2616 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
2617 moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge );
2618 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
2619 moveResizeGeom.moveRight( desktopArea.left() + left_marge );
2620 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
2621 moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
2622 if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
2630 if( rules()->checkMoveResizeMode
2631 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
2634 positionGeometryTip();
2636 else if( rules()->checkMoveResizeMode
2637 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent )
2640 positionGeometryTip();
2641 drawbound( moveResizeGeom );
2645 workspace()->clientMoved(globalPos, GET_QT_X_TIME());