00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include "client.h"
00020
#include "workspace.h"
00021
00022
#include <kapplication.h>
00023
#include <kglobal.h>
00024
#include <qpainter.h>
00025
#include <kwin.h>
00026
00027
#include "placement.h"
00028
#include "notifications.h"
00029
#include "geometrytip.h"
00030
00031
extern Time qt_x_time;
00032
00033
namespace KWinInternal
00034 {
00035
00036
00037
00038
00039
00043
void Workspace::desktopResized()
00044 {
00045 updateClientArea();
00046 checkElectricBorders();
00047 }
00048
00061
void Workspace::updateClientArea(
bool force )
00062 {
00063 QRect* new_areas =
new QRect[ numberOfDesktops() + 1 ];
00064 QRect all = QApplication::desktop()->geometry();
00065
for(
int i = 1;
00066 i <= numberOfDesktops();
00067 ++i )
00068 new_areas[ i ] = all;
00069
for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00070 {
00071 QRect r = (*it)->adjustedClientArea( all );
00072
if( r == all )
00073
continue;
00074
if( (*it)->isOnAllDesktops())
00075
for(
int i = 1;
00076 i <= numberOfDesktops();
00077 ++i )
00078 new_areas[ i ] = new_areas[ i ].intersect( r );
00079
else
00080 new_areas[ (*it)->desktop() ] = new_areas[ (*it)->desktop() ].intersect( r );
00081 }
00082
if( topmenu_space != NULL )
00083 {
00084 QRect topmenu_area = all;
00085 topmenu_area.setTop( topMenuHeight());
00086
for(
int i = 1;
00087 i <= numberOfDesktops();
00088 ++i )
00089 new_areas[ i ] = new_areas[ i ].intersect( topmenu_area );
00090 }
00091
00092
bool changed = force;
00093
for(
int i = 1;
00094 !changed && i <= numberOfDesktops();
00095 ++i )
00096
if( workarea[ i ] != new_areas[ i ] )
00097 changed =
true;
00098
if ( changed )
00099 {
00100
delete[] workarea;
00101 workarea = new_areas;
00102 new_areas = NULL;
00103 NETRect r;
00104
for(
int i = 1; i <= numberOfDesktops(); i++)
00105 {
00106 r.pos.x = workarea[ i ].x();
00107 r.pos.y = workarea[ i ].y();
00108 r.size.width = workarea[ i ].width();
00109 r.size.height = workarea[ i ].height();
00110 rootInfo->setWorkArea( i, r );
00111 }
00112
00113 updateTopMenuGeometry();
00114
for( ClientList::ConstIterator it = clients.begin();
00115 it != clients.end();
00116 ++it)
00117 (*it)->checkWorkspacePosition();
00118 }
00119
delete[] new_areas;
00120 }
00121
00122
void Workspace::updateClientArea()
00123 {
00124 updateClientArea(
false );
00125 }
00126
00127
00135 QRect Workspace::clientArea( clientAreaOption opt,
const QPoint& p,
int desktop )
const
00136
{
00137
if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
00138 desktop = currentDesktop();
00139 QRect rect = QApplication::desktop()->geometry();
00140 QDesktopWidget *desktopwidget = KApplication::desktop();
00141
00142
switch (opt)
00143 {
00144
case MaximizeArea:
00145
case MaximizeFullArea:
00146
if (options->xineramaMaximizeEnabled)
00147 rect = desktopwidget->screenGeometry(desktopwidget->screenNumber(p));
00148
break;
00149
case PlacementArea:
00150
if (options->xineramaPlacementEnabled)
00151 rect = desktopwidget->screenGeometry(desktopwidget->screenNumber(p));
00152
break;
00153
case MovementArea:
00154
if (options->xineramaMovementEnabled)
00155 rect = desktopwidget->screenGeometry(desktopwidget->screenNumber(p));
00156
break;
00157
case WorkArea:
00158
case FullArea:
00159
break;
00160
case ScreenArea:
00161 rect = desktopwidget->screenGeometry(desktopwidget->screenNumber(p));
00162
break;
00163 }
00164
00165
if( workarea[ desktop ].isNull() || opt == FullArea || opt == MaximizeFullArea
00166 || opt == ScreenArea || opt == MovementArea )
00167
return rect;
00168
00169
return workarea[ desktop ].intersect(rect);
00170 }
00171
00172 QRect Workspace::clientArea( clientAreaOption opt,
const Client* c )
const
00173
{
00174
return clientArea( opt, c->geometry().center(), c->desktop());
00175 }
00176
00182 QPoint Workspace::adjustClientPosition( Client* c, QPoint pos )
00183 {
00184
00185
00186
00187
if (options->windowSnapZone || options->borderSnapZone )
00188 {
00189
bool sOWO=options->snapOnlyWhenOverlapping;
00190 QRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
00191
int xmin = maxRect.left();
00192
int xmax = maxRect.right()+1;
00193
int ymin = maxRect.top();
00194
int ymax = maxRect.bottom()+1;
00195
00196
int cx(pos.x());
00197
int cy(pos.y());
00198
int cw(c->width());
00199
int ch(c->height());
00200
int rx(cx+cw);
00201
int ry(cy+ch);
00202
00203
int nx(cx), ny(cy);
00204
int deltaX(xmax);
00205
int deltaY(ymax);
00206
00207
int lx, ly, lrx, lry;
00208
00209
00210
int snap = options->borderSnapZone;
00211
if (snap)
00212 {
00213
if ((sOWO?(cx<xmin):
true) && (QABS(xmin-cx)<snap))
00214 {
00215 deltaX = xmin-cx;
00216 nx = xmin;
00217 }
00218
if ((sOWO?(rx>xmax):
true) && (QABS(rx-xmax)<snap) && (QABS(xmax-rx) < deltaX))
00219 {
00220 deltaX = rx-xmax;
00221 nx = xmax - cw;
00222 }
00223
00224
if ((sOWO?(cy<ymin):
true) && (QABS(ymin-cy)<snap))
00225 {
00226 deltaY = ymin-cy;
00227 ny = ymin;
00228 }
00229
if ((sOWO?(ry>ymax):
true) && (QABS(ry-ymax)<snap) && (QABS(ymax-ry) < deltaY))
00230 {
00231 deltaY =ry-ymax;
00232 ny = ymax - ch;
00233 }
00234 }
00235
00236
00237 snap = options->windowSnapZone;
00238
if (snap)
00239 {
00240 QValueList<Client *>::ConstIterator l;
00241
for (l = clients.begin();l != clients.end();++l )
00242 {
00243
if ((*l)->isOnDesktop(currentDesktop()) &&
00244 !(*l)->isMinimized()
00245 && (*l) != c )
00246 {
00247 lx = (*l)->x();
00248 ly = (*l)->y();
00249 lrx = lx + (*l)->width();
00250 lry = ly + (*l)->height();
00251
00252
if ( (( cy <= lry ) && ( cy >= ly )) ||
00253 (( ry >= ly ) && ( ry <= lry )) ||
00254 (( cy <= ly ) && ( ry >= lry )) )
00255 {
00256
if ((sOWO?(cx<lrx):
true) && (QABS(lrx-cx)<snap) && ( QABS(lrx -cx) < deltaX) )
00257 {
00258 deltaX = QABS( lrx - cx );
00259 nx = lrx;
00260 }
00261
if ((sOWO?(rx>lx):
true) && (QABS(rx-lx)<snap) && ( QABS( rx - lx )<deltaX) )
00262 {
00263 deltaX = QABS(rx - lx);
00264 nx = lx - cw;
00265 }
00266 }
00267
00268
if ( (( cx <= lrx ) && ( cx >= lx )) ||
00269 (( rx >= lx ) && ( rx <= lrx )) ||
00270 (( cx <= lx ) && ( rx >= lrx )) )
00271 {
00272
if ((sOWO?(cy<lry):
true) && (QABS(lry-cy)<snap) && (QABS( lry -cy ) < deltaY))
00273 {
00274 deltaY = QABS( lry - cy );
00275 ny = lry;
00276 }
00277
00278
if ((sOWO?(ry>ly):
true) && (QABS(ry-ly)<snap) && (QABS( ry - ly ) < deltaY ))
00279 {
00280 deltaY = QABS( ry - ly );
00281 ny = ly - ch;
00282 }
00283 }
00284 }
00285 }
00286 }
00287 pos = QPoint(nx, ny);
00288 }
00289
return pos;
00290 }
00291
00295
void Workspace::setClientIsMoving( Client *c )
00296 {
00297 Q_ASSERT(!c || !movingClient);
00298
00299 movingClient = c;
00300
if (movingClient)
00301 ++block_focus;
00302
else
00303 --block_focus;
00304 }
00305
00309
void Workspace::cascadeDesktop()
00310 {
00311
00312 Q_ASSERT( block_stacking_updates == 0 );
00313 ClientList::ConstIterator it(stackingOrder().begin());
00314
bool re_init_cascade_at_first_client =
true;
00315
for (; it != stackingOrder().end(); ++it)
00316 {
00317
if((!(*it)->isOnDesktop(currentDesktop())) ||
00318 ((*it)->isMinimized()) ||
00319 ((*it)->isOnAllDesktops()) ||
00320 (!(*it)->isMovable()) )
00321
continue;
00322 initPositioning->placeCascaded(*it, QRect(), re_init_cascade_at_first_client);
00323
00324
if (re_init_cascade_at_first_client)
00325 re_init_cascade_at_first_client =
false;
00326 }
00327 }
00328
00333
void Workspace::unclutterDesktop()
00334 {
00335 ClientList::Iterator it(clients.fromLast());
00336
for (; it != clients.end(); --it)
00337 {
00338
if((!(*it)->isOnDesktop(currentDesktop())) ||
00339 ((*it)->isMinimized()) ||
00340 ((*it)->isOnAllDesktops()) ||
00341 (!(*it)->isMovable()) )
00342
continue;
00343 initPositioning->placeSmart(*it, QRect());
00344 }
00345 }
00346
00347
00348
void Workspace::updateTopMenuGeometry( Client* c )
00349 {
00350
if( !managingTopMenus())
00351
return;
00352
if( c != NULL )
00353 {
00354 XEvent ev;
00355 ev.xclient.display = qt_xdisplay();
00356 ev.xclient.type = ClientMessage;
00357 ev.xclient.window = c->window();
00358
static Atom msg_type_atom = XInternAtom( qt_xdisplay(),
"_KDE_TOPMENU_MINSIZE", False );
00359 ev.xclient.message_type = msg_type_atom;
00360 ev.xclient.format = 32;
00361 ev.xclient.data.l[0] = qt_x_time;
00362 ev.xclient.data.l[1] = topmenu_space->width();
00363 ev.xclient.data.l[2] = topmenu_space->height();
00364 ev.xclient.data.l[3] = 0;
00365 ev.xclient.data.l[4] = 0;
00366 XSendEvent( qt_xdisplay(), c->window(), False, NoEventMask, &ev );
00367 KWin::setStrut( c->window(), 0, 0, topmenu_height, 0 );
00368 c->checkWorkspacePosition();
00369
return;
00370 }
00371
00372 QRect area;
00373 area = clientArea( MaximizeFullArea, QPoint( 0, 0 ), 1 );
00374 area.setHeight( topMenuHeight());
00375 topmenu_space->setGeometry( area );
00376
for( ClientList::ConstIterator it = topmenus.begin();
00377 it != topmenus.end();
00378 ++it )
00379 updateTopMenuGeometry( *it );
00380 }
00381
00382
00383
00384
00385
00386
00387
void Client::keepInArea(
const QRect& area )
00388 {
00389
if ( geometry().right() > area.right() && width() < area.width() )
00390
move( area.right() - width(), y() );
00391
if ( geometry().bottom() > area.bottom() && height() < area.height() )
00392
move( x(), area.bottom() - height() );
00393
if( !area.contains( geometry().topLeft() ))
00394 {
00395
int tx = x();
00396
int ty = y();
00397
if ( tx < area.x() )
00398 tx = area.x();
00399
if ( ty < area.y() )
00400 ty = area.y();
00401
move( tx, ty );
00402 }
00403 }
00404
00410
00411 QRect Client::adjustedClientArea(
const QRect& area )
const
00412
{
00413 QRect r = area;
00414
00415
if( isTopMenu())
00416
return r;
00417 NETStrut strut = info->strut();
00418
if ( strut.left > 0 )
00419 r.setLeft( r.left() + (
int) strut.left );
00420
if ( strut.top > 0 )
00421 r.setTop( r.top() + (
int) strut.top );
00422
if ( strut.right > 0 )
00423 r.setRight( r.right() - (
int) strut.right );
00424
if ( strut.bottom > 0 )
00425 r.setBottom( r.bottom() - (
int) strut.bottom );
00426
return r;
00427 }
00428
00429
00430
00431
00432
void Client::updateWorkareaDiffs()
00433 {
00434 QRect area = workspace()->clientArea( WorkArea,
this );
00435 QRect geom = geometry();
00436 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
00437 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
int Client::computeWorkareaDiff(
int left,
int right,
int a_left,
int a_right )
00449 {
00450
int left_diff = left - a_left;
00451
int right_diff = a_right - right;
00452
if( left_diff < 0 || right_diff < 0 )
00453
return INT_MIN;
00454
else
00455 {
00456
00457
int max_diff = ( a_right - a_left ) / 10;
00458
if( left_diff < right_diff )
00459
return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
00460
else if( left_diff > right_diff )
00461
return right_diff < max_diff ? right_diff + 1 : INT_MAX;
00462
return INT_MAX;
00463 }
00464 }
00465
00466
void Client::checkWorkspacePosition()
00467 {
00468
if( maximizeMode() !=
MaximizeRestore )
00469
00470 changeMaximize(
false,
false,
true );
00471
00472
if( isFullScreen())
00473 {
00474 QRect area = workspace()->clientArea( MaximizeFullArea,
this );
00475
if( geometry() != area )
00476
setGeometry( area );
00477
return;
00478 }
00479
if( isDock())
00480
return;
00481
if( isOverride())
00482
return;
00483
if( isTopMenu())
00484 {
00485
if( workspace()->managingTopMenus())
00486 {
00487 QRect area;
00488 ClientList mainclients = mainClients();
00489
if( mainclients.count() == 1 )
00490 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
00491
else
00492 area = workspace()->clientArea( MaximizeFullArea, QPoint( 0, 0 ),
desktop());
00493 area.setHeight( workspace()->topMenuHeight());
00494
00495
setGeometry( area );
00496 }
00497
return;
00498 }
00499
00500
if( !isShade())
00501 {
00502
int old_diff_x = workarea_diff_x;
00503
int old_diff_y = workarea_diff_y;
00504 updateWorkareaDiffs();
00505
00506
00507
00508
00509
00510
00511
if( workspace()->initializing())
00512
return;
00513
00514 QRect area = workspace()->clientArea( WorkArea,
this );
00515 QRect new_geom = geometry();
00516 QRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
00517 QRect tmp_area_x( area.left(), 0, area.width(), 0 );
00518 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
00519
00520 QRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
00521 QRect tmp_area_y( area.top(), 0, area.height(), 0 );
00522 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
00523 new_geom = QRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
00524 QRect final_geom( new_geom.topLeft(),
adjustedSize( new_geom.size()));
00525
if( final_geom != new_geom )
00526 {
00527
if( old_diff_x != INT_MAX && old_diff_x > 0 )
00528 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
00529
if( old_diff_y != INT_MAX && old_diff_y > 0 )
00530 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
00531 }
00532
if( final_geom != geometry() )
00533
setGeometry( final_geom );
00534
00535 }
00536 }
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
void Client::checkDirection(
int new_diff,
int old_diff, QRect& rect,
const QRect& area )
00549 {
00550
if( old_diff != INT_MIN )
00551 {
00552
if( old_diff == INT_MAX )
00553 {
00554
if( new_diff == INT_MIN )
00555 {
00556 rect.setLeft( area.left());
00557 rect.setRight( area.right());
00558 }
00559
return;
00560 }
00561
if(
isResizable())
00562 {
00563
if( rect.width() > area.width())
00564 rect.setWidth( area.width());
00565
if( rect.width() >= area.width() / 2 )
00566 {
00567
if( old_diff < 0 )
00568 rect.setLeft( area.left() + ( -old_diff - 1 ) );
00569
else
00570 rect.setRight( area.right() - ( old_diff - 1 ));
00571 }
00572 }
00573
if(
isMovable())
00574 {
00575
if( old_diff < 0 )
00576 rect.moveLeft( area.left() + ( -old_diff - 1 ));
00577
else
00578 rect.moveRight( area.right() - ( old_diff - 1 ));
00579 }
00580
00581
00582
00583
if(
isResizable())
00584 {
00585
if( old_diff < 0 )
00586 rect.setLeft( area.left() + ( -old_diff - 1 ) );
00587
else
00588 rect.setRight( area.right() - ( old_diff - 1 ));
00589 }
00590 }
00591
if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
00592 {
00593
if(
isMovable())
00594 {
00595
if( rect.left() < area.left() + 5 )
00596 rect.moveRight( area.left() + 5 );
00597
if( rect.right() > area.right() - 5 )
00598 rect.moveLeft( area.right() - 5 );
00599 }
00600 }
00601 }
00602
00606 QSize Client::adjustedSize(
const QSize& frame, Sizemode mode )
const
00607
{
00608
00609
00610 QSize wsize( frame.width() - ( border_left + border_right ),
00611 frame.height() - ( border_top + border_bottom ));
00612
00613
return sizeForClientSize( wsize, mode );
00614 }
00615
00624 QSize Client::sizeForClientSize(
const QSize& wsize, Sizemode mode )
const
00625
{
00626
int w = wsize.width();
00627
int h = wsize.height();
00628
if (w<1) w = 1;
00629
if (h<1) h = 1;
00630
00631
00632
00633 QSize min_size( xSizeHint.min_width, xSizeHint.min_height );
00634 QSize max_size( xSizeHint.max_width, xSizeHint.max_height );
00635
if( decoration != NULL )
00636 {
00637 QSize decominsize = decoration->
minimumSize();
00638 QSize border_size( border_left + border_right, border_top + border_bottom );
00639
if( border_size.width() > decominsize.width())
00640 decominsize.setWidth( border_size.width());
00641
if( border_size.height() > decominsize.height())
00642 decominsize.setHeight( border_size.height());
00643
if( decominsize.width() > min_size.width())
00644 min_size.setWidth( decominsize.width());
00645
if( decominsize.height() > min_size.height())
00646 min_size.setHeight( decominsize.height());
00647 }
00648 w = QMIN( max_size.width(), w );
00649 h = QMIN( max_size.height(), h );
00650 w = QMAX( min_size.width(), w );
00651 h = QMAX( min_size.height(), h );
00652
00653
int width_inc = xSizeHint.width_inc;
00654
int height_inc = xSizeHint.height_inc;
00655
int basew_inc = xSizeHint.min_width;
00656
int baseh_inc = xSizeHint.min_height;
00657 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
00658 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
if( xSizeHint.flags & PAspect )
00675 {
00676
double min_aspect_w = xSizeHint.min_aspect.x;
00677
double min_aspect_h = xSizeHint.min_aspect.y;
00678
double max_aspect_w = xSizeHint.max_aspect.x;
00679
double max_aspect_h = xSizeHint.max_aspect.y;
00680 w -= xSizeHint.base_width;
00681 h -= xSizeHint.base_height;
00682
int max_width = max_size.width() - xSizeHint.base_width;
00683
int min_width = min_size.width() - xSizeHint.base_width;
00684
int max_height = max_size.height() - xSizeHint.base_height;
00685
int min_height = min_size.height() - xSizeHint.base_height;
00686
#define ASPECT_CHECK_GROW_W \
00687
if( min_aspect_w * h > min_aspect_h * w ) \
00688
{ \
00689
int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
00690
if( w + delta <= max_width ) \
00691
w += delta; \
00692
}
00693
#define ASPECT_CHECK_SHRINK_H_GROW_W \
00694
if( min_aspect_w * h > min_aspect_h * w ) \
00695
{ \
00696
int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
00697
if( h - delta >= min_height ) \
00698
h -= delta; \
00699
else \
00700
{ \
00701
int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
00702
if( w + delta <= max_width ) \
00703
w += delta; \
00704
} \
00705
}
00706
#define ASPECT_CHECK_GROW_H \
00707
if( max_aspect_w * h < max_aspect_h * w ) \
00708
{ \
00709
int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
00710
if( h + delta <= max_height ) \
00711
h += delta; \
00712
}
00713
#define ASPECT_CHECK_SHRINK_W_GROW_H \
00714
if( max_aspect_w * h < max_aspect_h * w ) \
00715
{ \
00716
int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
00717
if( w - delta >= min_width ) \
00718
w -= delta; \
00719
else \
00720
{ \
00721
int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
00722
if( h + delta <= max_height ) \
00723
h += delta; \
00724
} \
00725
}
00726
switch( mode )
00727 {
00728
case SizemodeAny:
00729 {
00730 ASPECT_CHECK_SHRINK_H_GROW_W
00731 ASPECT_CHECK_SHRINK_W_GROW_H
00732 ASPECT_CHECK_GROW_H
00733 ASPECT_CHECK_GROW_W
00734
break;
00735 }
00736
case SizemodeFixedW:
00737 {
00738
00739 ASPECT_CHECK_GROW_H
00740 ASPECT_CHECK_SHRINK_H_GROW_W
00741 ASPECT_CHECK_SHRINK_W_GROW_H
00742 ASPECT_CHECK_GROW_W
00743
break;
00744 }
00745
case SizemodeFixedH:
00746 {
00747 ASPECT_CHECK_GROW_W
00748 ASPECT_CHECK_SHRINK_W_GROW_H
00749 ASPECT_CHECK_SHRINK_H_GROW_W
00750 ASPECT_CHECK_GROW_H
00751
break;
00752 }
00753
case SizemodeMax:
00754 {
00755
00756 ASPECT_CHECK_SHRINK_H_GROW_W
00757 ASPECT_CHECK_SHRINK_W_GROW_H
00758 ASPECT_CHECK_GROW_W
00759 ASPECT_CHECK_GROW_H
00760
break;
00761 }
00762
case SizemodeShaded:
00763
break;
00764 }
00765
#undef ASPECT_CHECK_SHRINK_H_GROW_W
00766
#undef ASPECT_CHECK_SHRINK_W_GROW_H
00767
#undef ASPECT_CHECK_GROW_W
00768
#undef ASPECT_CHECK_GROW_H
00769
w += xSizeHint.base_width;
00770 h += xSizeHint.base_height;
00771 }
00772
00773
if ( mode == SizemodeShaded && wsize.height() == 0 )
00774 h = 0;
00775
return QSize( w + border_left + border_right, h + border_top + border_bottom );
00776 }
00777
00781
void Client::getWmNormalHints()
00782 {
00783
long msize;
00784
if (XGetWMNormalHints(qt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
00785 xSizeHint.flags = 0;
00786
00787
00788
00789
00790
00791
if( xSizeHint.flags & PBaseSize )
00792 {
00793
if( ! ( xSizeHint.flags & PMinSize ))
00794 {
00795 xSizeHint.flags |= PMinSize;
00796 xSizeHint.min_width = xSizeHint.base_width;
00797 xSizeHint.min_height = xSizeHint.base_height;
00798 }
00799 }
00800
else
00801 xSizeHint.base_width = xSizeHint.base_height = 0;
00802
if( ! ( xSizeHint.flags & PMinSize ))
00803 xSizeHint.min_width = xSizeHint.min_height = 0;
00804
if( ! ( xSizeHint.flags & PMaxSize ))
00805 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
00806
else
00807 {
00808 xSizeHint.max_width = QMAX( xSizeHint.max_width, 1 );
00809 xSizeHint.max_height = QMAX( xSizeHint.max_height, 1 );
00810 }
00811
if( xSizeHint.flags & PResizeInc )
00812 {
00813 xSizeHint.width_inc = kMax( xSizeHint.width_inc, 1 );
00814 xSizeHint.height_inc = kMax( xSizeHint.height_inc, 1 );
00815 }
00816
else
00817 {
00818 xSizeHint.width_inc = 1;
00819 xSizeHint.height_inc = 1;
00820 }
00821
if( xSizeHint.flags & PAspect )
00822 {
00823 xSizeHint.min_aspect.y = kMax( xSizeHint.min_aspect.y, 1 );
00824 xSizeHint.max_aspect.y = kMax( xSizeHint.max_aspect.y, 1 );
00825 }
00826
else
00827 {
00828 xSizeHint.min_aspect.x = 1;
00829 xSizeHint.min_aspect.y = INT_MAX;
00830 xSizeHint.max_aspect.x = INT_MAX;
00831 xSizeHint.max_aspect.y = 1;
00832 }
00833
if( ! ( xSizeHint.flags & PWinGravity ))
00834 xSizeHint.win_gravity = NorthWestGravity;
00835
if( isManaged())
00836 {
00837 QSize new_size =
adjustedSize( size());
00838
if( new_size != size() && !isShade())
00839 resizeWithChecks( new_size );
00840 }
00841 updateAllowedActions();
00842 }
00843
00849
void Client::sendSyntheticConfigureNotify()
00850 {
00851 XConfigureEvent c;
00852 c.type = ConfigureNotify;
00853 c.send_event = True;
00854 c.event = window();
00855 c.window = window();
00856 c.x = x() + clientPos().x();
00857 c.y = y() + clientPos().y();
00858 c.width = clientSize().width();
00859 c.height = clientSize().height();
00860 c.border_width = 0;
00861 c.above = None;
00862 c.override_redirect = 0;
00863 XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
00864 }
00865
00866
const QPoint Client::calculateGravitation(
bool invert,
int gravity )
const
00867
{
00868
int dx, dy;
00869 dx = dy = 0;
00870
00871
if( gravity == 0 )
00872 gravity = xSizeHint.win_gravity;
00873
00874
00875
switch (gravity)
00876 {
00877
case NorthWestGravity:
00878
default:
00879 dx = border_left;
00880 dy = border_top;
00881
break;
00882
case NorthGravity:
00883 dx = 0;
00884 dy = border_top;
00885
break;
00886
case NorthEastGravity:
00887 dx = -border_right;
00888 dy = border_top;
00889
break;
00890
case WestGravity:
00891 dx = border_left;
00892 dy = 0;
00893
break;
00894
case CenterGravity:
00895
break;
00896
case StaticGravity:
00897 dx = 0;
00898 dy = 0;
00899
break;
00900
case EastGravity:
00901 dx = -border_right;
00902 dy = 0;
00903
break;
00904
case SouthWestGravity:
00905 dx = border_left ;
00906 dy = -border_bottom;
00907
break;
00908
case SouthGravity:
00909 dx = 0;
00910 dy = -border_bottom;
00911
break;
00912
case SouthEastGravity:
00913 dx = -border_right;
00914 dy = -border_bottom;
00915
break;
00916 }
00917
if( gravity != CenterGravity )
00918 {
00919 dx -= border_left;
00920 dy -= border_top;
00921 }
00922
else
00923 {
00924 dx = - ( border_left + border_right ) / 2;
00925 dy = - ( border_top + border_bottom ) / 2;
00926 }
00927
if( !invert )
00928
return QPoint( x() + dx, y() + dy );
00929
else
00930
return QPoint( x() - dx, y() - dy );
00931 }
00932
00933
void Client::configureRequest(
int value_mask,
int rx,
int ry,
int rw,
int rh,
int gravity )
00934 {
00935
if( gravity == 0 )
00936 gravity = xSizeHint.win_gravity;
00937
if( value_mask & ( CWX | CWY ))
00938 {
00939 QPoint new_pos = calculateGravitation(
true, gravity );
00940
if ( value_mask & CWX )
00941 new_pos.setX( rx );
00942
if ( value_mask & CWY )
00943 new_pos.setY( ry );
00944
00945
00946
00947
00948
00949
if ( new_pos.x() == x() + clientPos().x() &&
00950 new_pos.y() == y() + clientPos().y() && gravity == NorthWestGravity )
00951 {
00952 new_pos.setX( x());
00953 new_pos.setY( y());
00954 }
00955
00956
int nw = clientSize().width();
00957
int nh = clientSize().height();
00958
if ( value_mask & CWWidth )
00959 nw = rw;
00960
if ( value_mask & CWHeight )
00961 nh = rh;
00962 QSize ns = sizeForClientSize( QSize( nw, nh ) );
00963
00964
00965
if ( maximizeMode() !=
MaximizeFull
00966 || ns != size())
00967 {
00968 resetMaximize();
00969 ++block_geometry;
00970
move( new_pos );
00971 plainResize( ns );
00972 --block_geometry;
00973
setGeometry( QRect( calculateGravitation(
false, gravity ), size()), ForceGeometrySet );
00974 }
00975 }
00976
00977
if ( value_mask & (CWWidth | CWHeight )
00978 && ! ( value_mask & ( CWX | CWY )) )
00979 {
00980
if ( isShade())
00981 setShade( ShadeNone );
00982
00983
int nw = clientSize().width();
00984
int nh = clientSize().height();
00985
if ( value_mask & CWWidth )
00986 nw = rw;
00987
if ( value_mask & CWHeight )
00988 nh = rh;
00989 QSize ns = sizeForClientSize( QSize( nw, nh ) );
00990
00991
if( ns != size())
00992 {
00993 resetMaximize();
00994
int save_gravity = xSizeHint.win_gravity;
00995 xSizeHint.win_gravity = gravity;
00996 resizeWithChecks( ns );
00997 xSizeHint.win_gravity = save_gravity;
00998 }
00999 }
01000
01001
01002
01003 }
01004
01005
void Client::resizeWithChecks(
int w,
int h, ForceGeometry_t force )
01006 {
01007
int newx = x();
01008
int newy = y();
01009 QRect area = workspace()->clientArea( WorkArea,
this );
01010
01011
if( w > area.width())
01012 w = area.width();
01013
if( h > area.height())
01014 h = area.height();
01015 QSize tmp =
adjustedSize( QSize( w, h ));
01016 w = tmp.width();
01017 h = tmp.height();
01018
switch( xSizeHint.win_gravity )
01019 {
01020
case NorthWestGravity:
01021
default:
01022
break;
01023
case NorthGravity:
01024 newx = ( newx + width() / 2 ) - ( w / 2 );
01025
break;
01026
case NorthEastGravity:
01027 newx = newx + width() - w;
01028
break;
01029
case WestGravity:
01030 newy = ( newy + height() / 2 ) - ( h / 2 );
01031
break;
01032
case CenterGravity:
01033 newx = ( newx + width() / 2 ) - ( w / 2 );
01034 newy = ( newy + height() / 2 ) - ( h / 2 );
01035
break;
01036
case StaticGravity:
01037
01038
break;
01039
case EastGravity:
01040 newx = newx + width() - w;
01041 newy = ( newy + height() / 2 ) - ( h / 2 );
01042
break;
01043
case SouthWestGravity:
01044 newy = newy + height() - h;
01045
break;
01046
case SouthGravity:
01047 newx = ( newx + width() / 2 ) - ( w / 2 );
01048 newy = newy + height() - h;
01049
break;
01050
case SouthEastGravity:
01051 newx = newx + width() - w;
01052 newy = newy + height() - h;
01053
break;
01054 }
01055
01056
01057
if( workarea_diff_x != INT_MIN && w <= area.width())
01058 {
01059
if( newx < area.left())
01060 newx = area.left();
01061
if( newx + w > area.right() + 1 )
01062 newx = area.right() + 1 - w;
01063 assert( newx >= area.left() && newx + w <= area.right() + 1 );
01064 }
01065
if( workarea_diff_y != INT_MIN && h <= area.height())
01066 {
01067
if( newy < area.top())
01068 newy = area.top();
01069
if( newy + h > area.bottom() + 1 )
01070 newy = area.bottom() + 1 - h;
01071 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
01072 }
01073
setGeometry( newx, newy, w, h, force );
01074 }
01075
01076
01077
void Client::NETMoveResizeWindow(
int flags,
int x,
int y,
int width,
int height )
01078 {
01079
int gravity = flags & 0xff;
01080
int value_mask = 0;
01081
if( flags & ( 1 << 8 ))
01082 value_mask |= CWX;
01083
if( flags & ( 1 << 9 ))
01084 value_mask |= CWY;
01085
if( flags & ( 1 << 10 ))
01086 value_mask |= CWWidth;
01087
if( flags & ( 1 << 11 ))
01088 value_mask |= CWHeight;
01089 configureRequest( value_mask, x, y, width, height, gravity );
01090 }
01091
01095 bool Client::isResizable()
const
01096
{
01097
if ( !
isMovable() || !motif_may_resize || isSplash())
01098
return FALSE;
01099
01100
if ( ( xSizeHint.flags & PMaxSize) == 0 || (xSizeHint.flags & PMinSize ) == 0 )
01101
return TRUE;
01102
return ( xSizeHint.min_width < xSizeHint.max_width ) ||
01103 ( xSizeHint.min_height < xSizeHint.max_height );
01104 }
01105
01106
01107
01108
01109
bool Client::isMaximizable()
const
01110
{
01111
if ( maximizeMode() != MaximizeRestore )
01112
return TRUE;
01113
if( !
isResizable() || isToolbar())
01114
return false;
01115
if( xSizeHint.max_height < 32767 || xSizeHint.max_width < 32767 )
01116
return false;
01117
return true;
01118 }
01119
01120
01124 void Client::setGeometry(
int x,
int y,
int w,
int h, ForceGeometry_t force )
01125 {
01126
if( force == NormalGeometrySet && frame_geometry == QRect( x, y, w, h ))
01127
return;
01128 frame_geometry = QRect( x, y, w, h );
01129
if( !isShade())
01130 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01131
else
01132 {
01133
01134
if( !shade_geometry_change && h != border_top + border_bottom )
01135 {
01136 kdDebug() <<
"h:" << h <<
":t:" << border_top <<
":b:" << border_bottom << endl;
01137 assert(
false );
01138 }
01139 client_size = QSize( w - border_left - border_right, client_size.height());
01140 }
01141 updateWorkareaDiffs();
01142
if( block_geometry == 0 )
01143 {
01144 XMoveResizeWindow( qt_xdisplay(), frameId(), x, y, w, h );
01145 resizeDecoration( QSize( w, h ));
01146
if( !isShade())
01147 {
01148 QSize cs = clientSize();
01149 XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
01150 cs.width(), cs.height());
01151
01152 XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
01153 }
01154
if( shape())
01155 updateShape();
01156
01157 updateWorkareaDiffs();
01158 sendSyntheticConfigureNotify();
01159 }
01160 }
01161
01162
void Client::plainResize(
int w,
int h, ForceGeometry_t force )
01163 {
01164
if( force == NormalGeometrySet && frame_geometry.size() == QSize( w, h ))
01165
return;
01166 frame_geometry.setSize( QSize( w, h ));
01167
if( !isShade())
01168 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01169
else
01170 {
01171
01172
if( !shade_geometry_change && h != border_top + border_bottom )
01173 {
01174 kdDebug() <<
"h:" << h <<
":t:" << border_top <<
":b:" << border_bottom << endl;
01175 assert(
false );
01176 }
01177 client_size = QSize( w - border_left - border_right, client_size.height());
01178 }
01179 updateWorkareaDiffs();
01180
if( block_geometry == 0 )
01181 {
01182
01183 XResizeWindow( qt_xdisplay(), frameId(), w, h );
01184 resizeDecoration( QSize( w, h ));
01185
if( !isShade())
01186 {
01187 QSize cs = clientSize();
01188 XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
01189 cs.width(), cs.height());
01190 XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
01191 }
01192
if( shape())
01193 updateShape();
01194 updateWorkareaDiffs();
01195 sendSyntheticConfigureNotify();
01196 }
01197 }
01198
01202 void Client::move(
int x,
int y, ForceGeometry_t force )
01203 {
01204
if( force == NormalGeometrySet && frame_geometry.topLeft() == QPoint( x, y ))
01205
return;
01206 frame_geometry.moveTopLeft( QPoint( x, y ));
01207 updateWorkareaDiffs();
01208
if( block_geometry == 0 )
01209 {
01210 XMoveWindow( qt_xdisplay(), frameId(), x, y );
01211 sendSyntheticConfigureNotify();
01212 }
01213 }
01214
01215
01216
void Client::maximize( MaximizeMode m )
01217 {
01218
setMaximize( m & MaximizeVertical, m & MaximizeHorizontal );
01219 }
01220
01224 void Client::setMaximize(
bool vertically,
bool horizontally )
01225 {
01226 changeMaximize(
01227 max_mode & MaximizeVertical ? !vertically : vertically,
01228 max_mode & MaximizeHorizontal ? !horizontally : horizontally,
01229
false );
01230 }
01231
01232
void Client::changeMaximize(
bool vertical,
bool horizontal,
bool adjust )
01233 {
01234
if( !isMaximizable())
01235
return;
01236
01237 ++block_geometry;
01238
01239
if( isShade())
01240 setShade( ShadeNone );
01241
01242 MaximizeMode old_mode = max_mode;
01243
01244
if( !adjust )
01245 {
01246
if( vertical )
01247 max_mode =
MaximizeMode( max_mode ^ MaximizeVertical );
01248
if( horizontal )
01249 max_mode =
MaximizeMode( max_mode ^ MaximizeHorizontal );
01250 }
01251
01252
01253 Q_ASSERT( !( vertical && horizontal )
01254 || (( max_mode & MaximizeVertical != 0 ) == ( max_mode & MaximizeHorizontal != 0 )));
01255
01256
01257
bool maximalizing =
false;
01258
if( vertical && !(old_mode & MaximizeVertical ))
01259 {
01260 geom_restore.setTop( y());
01261 geom_restore.setHeight( height());
01262 maximalizing =
true;
01263 }
01264
if( horizontal && !( old_mode &
MaximizeHorizontal ))
01265 {
01266 geom_restore.setLeft( x());
01267 geom_restore.setWidth( width());
01268 maximalizing =
true;
01269 }
01270
01271
if( !adjust )
01272 {
01273
if( maximalizing )
01274 Notify::raise( Notify::Maximize );
01275
else
01276 Notify::raise( Notify::UnMaximize );
01277 }
01278
01279
if( decoration != NULL )
01280 decoration->
borders( border_left, border_right, border_top, border_bottom );
01281
01282 QRect clientArea = workspace()->clientArea( MaximizeArea,
this );
01283
01284
switch (max_mode)
01285 {
01286
01287
case MaximizeVertical:
01288 {
01289
if( old_mode &
MaximizeHorizontal )
01290 {
01291
if( geom_restore.width() == 0 )
01292 {
01293 plainResize(
adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH ));
01294 workspace()->placeSmart(
this, clientArea );
01295 }
01296
else
01297
setGeometry( QRect(QPoint( geom_restore.x(), clientArea.top()),
01298
adjustedSize(QSize( geom_restore.width(), clientArea.height()), SizemodeFixedH )));
01299 }
01300
else
01301
setGeometry( QRect(QPoint(x(), clientArea.top()),
01302
adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH )));
01303 info->setState( NET::MaxVert, NET::Max );
01304
break;
01305 }
01306
01307
case MaximizeHorizontal:
01308 {
01309
if( old_mode & MaximizeVertical )
01310 {
01311
if( geom_restore.height() == 0 )
01312 {
01313 plainResize(
adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW ));
01314 workspace()->placeSmart(
this, clientArea );
01315 }
01316
else
01317
setGeometry( QRect( QPoint(clientArea.left(), geom_restore.y()),
01318
adjustedSize(QSize(clientArea.width(), geom_restore.height()), SizemodeFixedW )));
01319 }
01320
else
01321
setGeometry( QRect( QPoint(clientArea.left(), y()),
01322
adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW )));
01323 info->setState( NET::MaxHoriz, NET::Max );
01324
break;
01325 }
01326
01327
case MaximizeRestore:
01328 {
01329 QRect restore = geometry();
01330
01331
if( old_mode & MaximizeVertical )
01332 {
01333 restore.setTop( geom_restore.top());
01334 restore.setBottom( geom_restore.bottom());
01335 }
01336
if( old_mode &
MaximizeHorizontal )
01337 {
01338 restore.setLeft( geom_restore.left());
01339 restore.setRight( geom_restore.right());
01340 }
01341
if( !restore.isValid())
01342 {
01343 QSize s = QSize( clientArea.width()*2/3, clientArea.height()*2/3 );
01344
if( geom_restore.width() > 0 )
01345 s.setWidth( geom_restore.width());
01346
if( geom_restore.height() > 0 )
01347 s.setHeight( geom_restore.height());
01348 plainResize(
adjustedSize( s ));
01349 workspace()->placeSmart(
this, clientArea );
01350 restore = geometry();
01351
if( geom_restore.width() > 0 )
01352 restore.moveLeft( geom_restore.x());
01353
if( geom_restore.height() > 0 )
01354 restore.moveTop( geom_restore.y());
01355 }
01356
setGeometry( restore );
01357 info->setState( 0, NET::Max );
01358
break;
01359 }
01360
01361
case MaximizeFull:
01362 {
01363 QSize adjSize =
adjustedSize(clientArea.size(), SizemodeMax );
01364 QRect r = QRect(clientArea.topLeft(), adjSize);
01365
setGeometry( r );
01366 info->setState( NET::Max, NET::Max );
01367
break;
01368 }
01369
default:
01370
break;
01371 }
01372
01373 --block_geometry;
01374
setGeometry( geometry(), ForceGeometrySet );
01375
01376 updateAllowedActions();
01377
if( decoration != NULL )
01378 decoration->
maximizeChange();
01379 }
01380
01381
void Client::resetMaximize()
01382 {
01383
if( max_mode ==
MaximizeRestore )
01384
return;
01385 max_mode =
MaximizeRestore;
01386 Notify::raise( Notify::UnMaximize );
01387 info->setState( 0, NET::Max );
01388 updateAllowedActions();
01389
if( decoration != NULL )
01390 decoration->
borders( border_left, border_right, border_top, border_bottom );
01391
setGeometry( geometry(), ForceGeometrySet );
01392
if( decoration != NULL )
01393 decoration->
maximizeChange();
01394 }
01395
01396
bool Client::isFullScreenable(
bool fullscreen_hack )
const
01397
{
01398
if( fullscreen_hack )
01399
return isNormalWindow() || isOverride();
01400
else
01401
return !isSpecialWindow();
01402 }
01403
01404
bool Client::userCanSetFullScreen()
const
01405
{
01406
return isNormalWindow() && fullscreen_mode != FullScreenHack
01407 && ( isMaximizable() || isFullScreen());
01408 }
01409
01410
void Client::setFullScreen(
bool set,
bool user )
01411 {
01412
if( !isFullScreen() && !set )
01413
return;
01414
if( fullscreen_mode == FullScreenHack )
01415
return;
01416
if( user && !userCanSetFullScreen())
01417
return;
01418 setShade( ShadeNone );
01419
bool was_fs = isFullScreen();
01420
if( !was_fs )
01421 geom_fs_restore = geometry();
01422 fullscreen_mode = set ? FullScreenNormal : FullScreenNone;
01423
if( was_fs == isFullScreen())
01424
return;
01425 StackingUpdatesBlocker blocker( workspace());
01426 workspace()->updateClientLayer(
this );
01427 info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
01428 updateDecoration(
false,
false );
01429
if( isFullScreen())
01430
setGeometry( workspace()->clientArea( MaximizeFullArea,
this ));
01431
else
01432 {
01433
if( maximizeMode() != MaximizeRestore )
01434 changeMaximize(
false,
false,
true );
01435
else if( !geom_fs_restore.isNull())
01436
setGeometry( geom_fs_restore );
01437
01438
else
01439 {
01440
setGeometry( workspace()->clientArea( MaximizeArea,
this ));
01441 }
01442 }
01443 }
01444
01445
01446
static QRect* visible_bound = 0;
01447
static GeometryTip* geometryTip = 0;
01448
01449
void Client::drawbound(
const QRect& geom )
01450 {
01451 assert( visible_bound == NULL );
01452 visible_bound =
new QRect( geom );
01453 doDrawbound( *visible_bound,
false );
01454 }
01455
01456
void Client::clearbound()
01457 {
01458
if( visible_bound == NULL )
01459
return;
01460 doDrawbound( *visible_bound,
true );
01461
delete visible_bound;
01462 visible_bound = 0;
01463 }
01464
01465
void Client::doDrawbound(
const QRect& geom,
bool clear )
01466 {
01467
if( decoration != NULL && decoration->
drawbound( geom, clear ))
01468
return;
01469 QPainter p ( workspace()->desktopWidget() );
01470 p.setPen( QPen( Qt::white, 5 ) );
01471 p.setRasterOp( Qt::XorROP );
01472 p.drawRect( geom );
01473 }
01474
01475
void Client::positionGeometryTip()
01476 {
01477 assert( isMove() || isResize());
01478
01479
if (options->showGeometryTip())
01480 {
01481
if( !geometryTip )
01482 {
01483
bool save_under = ( isMove() && options->moveMode != Options::Opaque )
01484 || ( isResize() && options->resizeMode != Options::Opaque );
01485 geometryTip =
new GeometryTip( &xSizeHint, save_under );
01486 }
01487 QRect wgeom( moveResizeGeom );
01488 wgeom.setWidth( wgeom.width() - ( width() - clientSize().width()));
01489 wgeom.setHeight( wgeom.height() - ( height() - clientSize().height()));
01490
if( isShade())
01491 wgeom.setHeight( 0 );
01492 geometryTip->setGeometry( wgeom );
01493
if( !geometryTip->isVisible())
01494 {
01495 geometryTip->show();
01496 geometryTip->raise();
01497 }
01498 }
01499 }
01500
01501
class EatAllPaintEvents
01502 :
public QObject
01503 {
01504
protected:
01505
virtual bool eventFilter( QObject* o, QEvent* e )
01506 {
return e->type() == QEvent::Paint && o != geometryTip; }
01507 };
01508
01509
static EatAllPaintEvents* eater = 0;
01510
01511
bool Client::startMoveResize()
01512 {
01513 assert( !moveResizeMode );
01514 assert( QWidget::keyboardGrabber() == NULL );
01515 assert( QWidget::mouseGrabber() == NULL );
01516
if( QApplication::activePopupWidget() != NULL )
01517
return false;
01518
bool has_grab =
false;
01519
01520
01521
01522 XSetWindowAttributes attrs;
01523 QRect r = workspace()->clientArea( FullArea,
this );
01524 move_resize_grab_window = XCreateWindow( qt_xdisplay(), workspace()->rootWin(), r.x(), r.y(),
01525 r.width(), r.height(), 0, CopyFromParent, InputOnly, CopyFromParent, 0, &attrs );
01526 XMapRaised( qt_xdisplay(), move_resize_grab_window );
01527
if( XGrabPointer( qt_xdisplay(), move_resize_grab_window, False,
01528 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
01529 GrabModeAsync, GrabModeAsync, None, cursor.handle(), qt_x_time ) == Success )
01530 has_grab =
true;
01531
if( XGrabKeyboard( qt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, qt_x_time ) == Success )
01532 has_grab =
true;
01533
if( !has_grab )
01534 {
01535 XDestroyWindow( qt_xdisplay(), move_resize_grab_window );
01536 move_resize_grab_window = None;
01537
return false;
01538 }
01539
if ( maximizeMode() != MaximizeRestore )
01540 resetMaximize();
01541 moveResizeMode =
true;
01542 workspace()->setClientIsMoving(
this);
01543 initialMoveResizeGeom = moveResizeGeom = geometry();
01544 checkUnrestrictedMoveResize();
01545
if ( ( isMove() && options->moveMode != Options::Opaque )
01546 || ( isResize() && options->resizeMode != Options::Opaque ) )
01547 {
01548 grabXServer();
01549 kapp->sendPostedEvents();
01550
01551
01552
01553
01554
01555 eater =
new EatAllPaintEvents;
01556 kapp->installEventFilter( eater );
01557 }
01558 Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
01559
return true;
01560 }
01561
01562
void Client::finishMoveResize(
bool cancel )
01563 {
01564 leaveMoveResize();
01565
if( cancel )
01566
setGeometry( initialMoveResizeGeom );
01567
else
01568
setGeometry( moveResizeGeom );
01569
01570 Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
01571 }
01572
01573
void Client::leaveMoveResize()
01574 {
01575 clearbound();
01576
if (geometryTip)
01577 {
01578 geometryTip->hide();
01579
delete geometryTip;
01580 geometryTip = NULL;
01581 }
01582
if ( ( isMove() && options->moveMode != Options::Opaque )
01583 || ( isResize() && options->resizeMode != Options::Opaque ) )
01584 ungrabXServer();
01585 XUngrabKeyboard( qt_xdisplay(), qt_x_time );
01586 XUngrabPointer( qt_xdisplay(), qt_x_time );
01587 XDestroyWindow( qt_xdisplay(), move_resize_grab_window );
01588 move_resize_grab_window = None;
01589 workspace()->setClientIsMoving(0);
01590
if( move_faked_activity )
01591 workspace()->unfakeActivity(
this );
01592 move_faked_activity =
false;
01593 moveResizeMode =
false;
01594
delete eater;
01595 eater = 0;
01596 }
01597
01598
01599
01600
01601
01602
void Client::checkUnrestrictedMoveResize()
01603 {
01604
if( unrestrictedMoveResize )
01605
return;
01606 QRect desktopArea = workspace()->clientArea( WorkArea, moveResizeGeom.center(),
desktop());
01607
int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
01608
01609
01610 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
01611 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
01612
01613 titlebar_marge = initialMoveResizeGeom.height();
01614 top_marge = border_bottom;
01615 bottom_marge = border_top;
01616
if( isResize())
01617 {
01618
if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
01619 unrestrictedMoveResize =
true;
01620
if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
01621 unrestrictedMoveResize =
true;
01622
if( moveResizeGeom.right() < desktopArea.left() + left_marge )
01623 unrestrictedMoveResize =
true;
01624
if( moveResizeGeom.left() > desktopArea.right() - right_marge )
01625 unrestrictedMoveResize =
true;
01626
if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
01627 unrestrictedMoveResize =
true;
01628 }
01629
if( isMove())
01630 {
01631
if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
01632 unrestrictedMoveResize =
true;
01633
01634
if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
01635 unrestrictedMoveResize =
true;
01636
if( moveResizeGeom.right() < desktopArea.left() + left_marge )
01637 unrestrictedMoveResize =
true;
01638
if( moveResizeGeom.left() > desktopArea.right() - right_marge )
01639 unrestrictedMoveResize =
true;
01640 }
01641 }
01642
01643
void Client::handleMoveResize(
int x,
int y,
int x_root,
int y_root )
01644 {
01645
if(( mode == PositionCenter && !
isMovable())
01646 || ( mode != PositionCenter && ( isShade() || !
isResizable())))
01647
return;
01648
01649
if ( !moveResizeMode )
01650 {
01651 QPoint p( QPoint( x, y ) - moveOffset );
01652
if (p.manhattanLength() >= 6)
01653 {
01654
if( !startMoveResize())
01655 {
01656 buttonDown =
false;
01657 setCursor( mode );
01658
return;
01659 }
01660 }
01661
else
01662
return;
01663 }
01664
01665
01666
if ( mode != PositionCenter && shade_mode != ShadeNone )
01667 setShade( ShadeNone );
01668
01669 QPoint globalPos( x_root, y_root );
01670
01671
01672 QPoint topleft = globalPos - moveOffset;
01673 QPoint bottomright = globalPos + invertedMoveOffset;
01674 QRect previousMoveResizeGeom = moveResizeGeom;
01675
01676
01677
01678
01679
01680 QRect desktopArea = workspace()->clientArea( WorkArea, globalPos,
desktop());
01681
int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
01682
if( unrestrictedMoveResize )
01683 left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
01684
else
01685 {
01686
01687 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
01688 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
01689
01690 titlebar_marge = initialMoveResizeGeom.height();
01691 top_marge = border_bottom;
01692 bottom_marge = border_top;
01693 }
01694
01695
bool update =
false;
01696
if( isResize())
01697 {
01698
01699 QRect orig = initialMoveResizeGeom;
01700 Sizemode sizemode = SizemodeAny;
01701
switch ( mode )
01702 {
01703
case PositionTopLeft:
01704 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
01705
break;
01706
case PositionBottomRight:
01707 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
01708
break;
01709
case PositionBottomLeft:
01710 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
01711
break;
01712
case PositionTopRight:
01713 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
01714
break;
01715
case PositionTop:
01716 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), orig.bottomRight() ) ;
01717 sizemode = SizemodeFixedH;
01718
break;
01719
case PositionBottom:
01720 moveResizeGeom = QRect( orig.topLeft(), QPoint( orig.right(), bottomright.y() ) ) ;
01721 sizemode = SizemodeFixedH;
01722
break;
01723
case PositionLeft:
01724 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), orig.bottomRight() ) ;
01725 sizemode = SizemodeFixedW;
01726
break;
01727
case PositionRight:
01728 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), orig.bottom() ) ) ;
01729 sizemode = SizemodeFixedW;
01730
break;
01731
case PositionCenter:
01732
default:
01733 assert(
false );
01734
break;
01735 }
01736
01737
01738
if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
01739 moveResizeGeom.setBottom( desktopArea.top() + top_marge );
01740
if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
01741 moveResizeGeom.setTop( desktopArea.bottom() - bottom_marge );
01742
if( moveResizeGeom.right() < desktopArea.left() + left_marge )
01743 moveResizeGeom.setRight( desktopArea.left() + left_marge );
01744
if( moveResizeGeom.left() > desktopArea.right() - right_marge )
01745 moveResizeGeom.setLeft(desktopArea.right() - right_marge );
01746
if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
01747 moveResizeGeom.setTop( desktopArea.top());
01748
01749 QSize size =
adjustedSize( moveResizeGeom.size(), sizemode );
01750
01751 topleft = QPoint( moveResizeGeom.right() - size.width() + 1, moveResizeGeom.bottom() - size.height() + 1 );
01752 bottomright = QPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
01753 orig = moveResizeGeom;
01754
switch ( mode )
01755 {
01756
case PositionTopLeft:
01757 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
01758
break;
01759
case PositionBottomRight:
01760 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
01761
break;
01762
case PositionBottomLeft:
01763 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
01764
break;
01765
case PositionTopRight:
01766 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
01767
break;
01768
01769
01770
01771
case PositionTop:
01772 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
01773
break;
01774
case PositionBottom:
01775 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
01776
break;
01777
case PositionLeft:
01778 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), QPoint( orig.right(), bottomright.y()));
01779
break;
01780
case PositionRight:
01781 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
01782
break;
01783
case PositionCenter:
01784
default:
01785 assert(
false );
01786
break;
01787 }
01788
if( moveResizeGeom.size() != previousMoveResizeGeom.size())
01789 update =
true;
01790 }
01791
else if( isMove())
01792 {
01793 assert( mode == PositionCenter );
01794
01795 moveResizeGeom.moveTopLeft( topleft );
01796 moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition(
this, moveResizeGeom.topLeft() ) );
01797
01798
if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
01799 moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 );
01800
01801
if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
01802 moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge );
01803
if( moveResizeGeom.right() < desktopArea.left() + left_marge )
01804 moveResizeGeom.moveRight( desktopArea.left() + left_marge );
01805
if( moveResizeGeom.left() > desktopArea.right() - right_marge )
01806 moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
01807
if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
01808 update =
true;
01809 }
01810
else
01811 assert(
false );
01812
01813
if( update )
01814 {
01815
if(( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
01816 {
01817
setGeometry( moveResizeGeom );
01818 positionGeometryTip();
01819 }
01820
else if(( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent )
01821 {
01822 clearbound();
01823 positionGeometryTip();
01824 drawbound( moveResizeGeom );
01825 }
01826 }
01827
if ( isMove() )
01828 workspace()->clientMoved(globalPos, qt_x_time);
01829 }
01830
01831
01832 }