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