16#include <tqapplication.h>
18#include <tqdatetime.h>
21#include <tdeprocess.h>
23#include <tdestandarddirs.h>
24#include <tqwhatsthis.h>
26#include <kiconloader.h>
39#include "notifications.h"
42#include <X11/extensions/shape.h>
47extern Atom tqt_wm_state;
48extern Atom tqt_window_role;
49extern Atom tqt_sm_client_id;
52static const int SHADOW_DELAY = 200;
68static TQValueList<ShadowRegion> shadowRegions;
101 bridge( new Bridge( this )),
102 inhibitConfigureRequests(false),
103 move_faked_activity( false ),
104 move_resize_grab_window( None ),
105 transient_for( NULL ),
106 transient_for_id( None ),
107 original_transient_for_id( None ),
109 window_group( None ),
110 in_layer( UnknownLayer ),
112 process_killer( NULL ),
113 process_resumer( NULL ),
114 user_time( CurrentTime ),
115 allowed_actions( 0 ),
116 postpone_geometry_updates( 0 ),
117 pending_geometry_update( false ),
118 shade_geometry_change( false ),
123 opacity_( Opacity::Opaque ),
124 demandAttentionKNotifyTimer( NULL ),
125 activeMaximizing(false),
132 configureRequestTimer =
new TQTimer(
this);
133 connect(configureRequestTimer, TQ_SIGNAL(timeout()), TQ_SLOT(configureRequestTimeout()));
135 shadowDelayTimer =
new TQTimer(
this);
136 opacityCache = &activeOpacityCache;
137 shadowAfterClient = NULL;
140 connect(shadowDelayTimer, TQ_SIGNAL(timeout()), TQ_SLOT(drawShadow()));
143 mapping_state = WithdrawnState;
146 mode = PositionCenter;
148 moveResizeMode =
false;
152 shade_mode = ShadeNone;
158 motif_noborder =
false;
159 motif_may_move =
true;
160 motif_may_resize =
true;
161 motif_may_close =
true;
162 fullscreen_mode = FullScreenNone;
163 skip_taskbar =
false;
164 original_skip_taskbar =
false;
169 user_noborder =
false;
171 ignore_focus_stealing =
false;
172 demands_attention =
false;
173 check_active_modal =
false;
183 max_mode = MaximizeRestore;
184 maxmode_restore = MaximizeRestore;
188 frame_geometry = TQRect( 0, 0, 100, 100 );
189 client_size = TQSize( 100, 100 );
190 custom_opacity =
false;
191 rule_opacity_active = 0;
192 rule_opacity_inactive = 0;
202 assert(!moveResizeMode);
203 assert( client == None );
204 assert( frame == None && wrapper == None );
205 assert( decoration == NULL );
206 assert( postpone_geometry_updates == 0 );
207 assert( !check_active_modal );
213void Client::deleteClient( Client* c, allowed_t )
225 workspace()->discardUsedWindowRules(
this,
true );
226 StackingUpdatesBlocker blocker( workspace());
227 if (!custom_opacity) setOpacity(Opacity::Opaque);
231 drawIntersectingShadows();
233 ++postpone_geometry_updates;
237 setMappingState( WithdrawnState );
241 workspace()->clientHidden(
this );
242 XUnmapWindow( tqt_xdisplay(), frameId());
247 workspace()->removeClient(
this, Allowed );
250 info->setDesktop( 0 );
252 info->setState( 0, info->state());
254 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
255 XDeleteProperty( tqt_xdisplay(), client, atoms->net_frame_extents );
256 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
257 XReparentWindow( tqt_xdisplay(), client, workspace()->rootWin(), x(), y());
258 XRemoveFromSaveSet( tqt_xdisplay(), client );
259 XSelectInput( tqt_xdisplay(), client, NoEventMask );
262 XMapWindow( tqt_xdisplay(), client );
269 XUnmapWindow( tqt_xdisplay(), client );
272 XDestroyWindow( tqt_xdisplay(), wrapper );
274 XDestroyWindow( tqt_xdisplay(), frame );
276 --postpone_geometry_updates;
277 checkNonExistentClients();
278 deleteClient(
this, Allowed );
284void Client::destroyClient()
288 workspace()->discardUsedWindowRules(
this,
true );
289 StackingUpdatesBlocker blocker( workspace());
293 drawIntersectingShadows();
295 ++postpone_geometry_updates;
298 workspace()->clientHidden(
this );
301 workspace()->removeClient(
this, Allowed );
303 XDestroyWindow( tqt_xdisplay(), wrapper );
305 XDestroyWindow( tqt_xdisplay(), frame );
307 --postpone_geometry_updates;
308 checkNonExistentClients();
309 deleteClient(
this, Allowed );
312void Client::updateDecoration(
bool check_workspace_pos,
bool force )
314 if( !force && (( decoration == NULL && noBorder())
315 || ( decoration != NULL && !noBorder())))
317 bool do_show =
false;
318 postponeGeometryUpdates(
true );
323 setMask( TQRegion());
324 decoration = workspace()->createDecoration( bridge );
327 decoration->widget()->installEventFilter(
this );
328 XReparentWindow( tqt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
329 decoration->widget()->lower();
330 decoration->borders( border_left, border_right, border_top, border_bottom );
331 int save_workarea_diff_x = workarea_diff_x;
332 int save_workarea_diff_y = workarea_diff_y;
333 move( calculateGravitation(
false ));
334 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
335 workarea_diff_x = save_workarea_diff_x;
336 workarea_diff_y = save_workarea_diff_y;
341 if( check_workspace_pos )
342 checkWorkspacePosition();
343 postponeGeometryUpdates(
false );
345 decoration->widget()->show();
346 updateFrameExtents();
347 updateOpacityCache();
350void Client::destroyDecoration()
352 if( decoration != NULL )
356 TQPoint grav = calculateGravitation(
true );
357 border_left = border_right = border_top = border_bottom = 0;
358 setMask( TQRegion());
359 int save_workarea_diff_x = workarea_diff_x;
360 int save_workarea_diff_y = workarea_diff_y;
361 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
363 workarea_diff_x = save_workarea_diff_x;
364 workarea_diff_y = save_workarea_diff_y;
368void Client::checkBorderSizes()
370 if( decoration == NULL )
372 int new_left, new_right, new_top, new_bottom;
373 decoration->borders( new_left, new_right, new_top, new_bottom );
374 if( new_left == border_left && new_right == border_right
375 && new_top == border_top && new_bottom == border_bottom )
377 GeometryUpdatesPostponer blocker(
this );
378 move( calculateGravitation(
true ));
379 border_left = new_left;
380 border_right = new_right;
381 border_top = new_top;
382 border_bottom = new_bottom;
383 if (border_left != new_left ||
384 border_right != new_right ||
385 border_top != new_top ||
386 border_bottom != new_bottom)
387 move( calculateGravitation(
false ));
388 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
389 checkWorkspacePosition();
392void Client::detectNoBorder()
394 if( Shape::hasShape( window()))
399 switch( windowType())
421 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
425void Client::detectShapable()
427 if( Shape::hasShape( window()))
429 switch( windowType())
449void Client::updateFrameExtents()
452 strut.left = border_left;
453 strut.right = border_right;
454 strut.top = border_top;
455 strut.bottom = border_bottom;
456 info->setFrameExtents( strut );
464void Client::resizeDecoration(
const TQSize& s )
466 if( decoration == NULL )
468 TQSize oldsize = decoration->widget()->size();
469 decoration->resize( s );
472 TQResizeEvent e( s, oldsize );
473 TQApplication::sendEvent( decoration->widget(), &e );
475 if (!moveResizeMode && options->shadowEnabled(isActive()))
479 updateOpacityCache();
483bool Client::noBorder()
const
485 return noborder || isFullScreen() || user_noborder || motif_noborder;
488bool Client::userCanSetNoBorder()
const
490 return !noborder && !isFullScreen() && !isShade();
493bool Client::isUserNoBorder()
const
495 return user_noborder;
498void Client::setUserNoBorder(
bool set )
500 if( !userCanSetNoBorder())
502 set = rules()->checkNoBorder( set );
503 if( user_noborder == set )
506 updateDecoration(
true,
false );
510bool Client::isModalSystemNotification()
const
512 unsigned char *data = 0;
515 unsigned long n, left;
516 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
517 if (result == Success && data && format == 32 )
524void Client::updateShape()
527 if( shape() && !noBorder())
530 updateDecoration(
true );
532 updateOpacityCache();
535 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
536 clientPos().x(), clientPos().y(),
537 window(), ShapeBounding, ShapeSet);
543 if( Shape::version() >= 0x11 )
553 static Window helper_window = None;
554 if( helper_window == None )
555 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
556 0, 0, 1, 1, 0, 0, 0 );
557 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
558 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
559 frameId(), ShapeBounding, ShapeSet );
560 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
561 clientPos().x(), clientPos().y(),
562 window(), ShapeBounding, ShapeSubtract );
563 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
564 clientPos().x(), clientPos().y(),
565 window(), ShapeInput, ShapeUnion );
566 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
567 helper_window, ShapeInput, ShapeSet );
571void Client::setMask(
const TQRegion& reg,
int mode )
575 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
577 else if( mode == X::Unsorted )
578 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
579 reg.handle(), ShapeSet );
582 TQMemArray< TQRect > rects = reg.rects();
583 XRectangle* xrects =
new XRectangle[ rects.count() ];
584 for(
unsigned int i = 0;
588 xrects[ i ].x = rects[ i ].x();
589 xrects[ i ].y = rects[ i ].y();
590 xrects[ i ].width = rects[ i ].width();
591 xrects[ i ].height = rects[ i ].height();
593 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
594 xrects, rects.count(), ShapeSet, mode );
600TQRegion Client::mask()
const
603 return TQRegion( 0, 0, width(), height());
607void Client::setShapable(
bool b)
610 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
613void Client::hideClient(
bool hide )
626 if( isSpecialWindow())
628 if( isModalSystemNotification())
632 bool shown_mainwindow =
false;
633 ClientList mainclients = mainClients();
634 for( ClientList::ConstIterator it = mainclients.begin();
635 it != mainclients.end();
638 if( (*it)->isShown(
true ))
639 shown_mainwindow =
true;
641 if( !shown_mainwindow )
647 if( transientFor() != NULL )
649 if( !wantsTabFocus())
659 if( isModalSystemNotification())
673 info->setState(0, NET::Shaded);
675 Notify::raise( Notify::Minimize );
678 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
679 animateMinimizeOrUnminimize(
true );
684 updateAllowedActions();
685 workspace()->updateMinimizedOfTransients(
this );
687 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
690void Client::unminimize(
bool avoid_animation )
692 if (!queryUserSuspendedResume())
699 info->setState(NET::Shaded, NET::Shaded);
701 Notify::raise( Notify::UnMinimize );
703 if( isOnCurrentDesktop() && isShown(
true ))
705 if( mainClients().isEmpty() && !avoid_animation )
706 animateMinimizeOrUnminimize(
false );
709 updateAllowedActions();
710 workspace()->updateMinimizedOfTransients(
this );
714extern bool blockAnimation;
716void Client::animateMinimizeOrUnminimize(
bool minimize )
718 if ( blockAnimation )
720 if ( !options->animateMinimize )
723 if( decoration != NULL && decoration->animateMinimize(
minimize ))
730 float lf,rf,tf,bf,step;
732 int speed = options->animateMinimizeSpeed;
738 step = 40. * (11 - speed );
740 NETRect r = info->iconGeometry();
741 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
742 if ( !icongeom.isValid() )
745 TQPixmap pm = animationPixmap(
minimize ? width() : icongeom.width() );
747 TQRect before, after;
750 before = TQRect( x(), y(), width(), pm.height() );
751 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
755 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
756 after = TQRect( x(), y(), width(), pm.height() );
759 lf = (after.left() - before.left())/step;
760 rf = (after.right() - before.right())/step;
761 tf = (after.top() - before.top())/step;
762 bf = (after.bottom() - before.bottom())/step;
766 TQRect area = before;
774 TQPainter p ( workspace()->desktopWidget() );
775 bool need_to_clear =
false;
781 pm = animationPixmap( area.width() );
782 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
783 p.drawPixmap( area.x(), area.y(), pm );
786 p.drawPixmap( area2.x(), area2.y(), pm3 );
787 need_to_clear =
false;
791 XFlush(tqt_xdisplay());
792 XSync( tqt_xdisplay(), False );
796 area.setLeft(before.left() +
int(diff*lf));
797 area.setRight(before.right() +
int(diff*rf));
798 area.setTop(before.top() +
int(diff*tf));
799 area.setBottom(before.bottom() +
int(diff*bf));
802 if ( area2.intersects( area ) )
803 p.drawPixmap( area2.x(), area2.y(), pm2 );
807 need_to_clear =
true;
810 }
while ( t.elapsed() < step);
811 if (area2 == area || need_to_clear )
812 p.drawPixmap( area2.x(), area2.y(), pm2 );
822TQPixmap Client::animationPixmap(
int w )
824 TQFont font = options->font(isActive());
825 TQFontMetrics fm( font );
826 TQPixmap pm( w, fm.lineSpacing() );
827 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
829 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
830 p.setFont(options->font(isActive()));
831 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
836bool Client::isShadeable()
const
838 return !isSpecialWindow() && !noBorder();
841void Client::setShade( ShadeMode mode )
845 if( isModalSystemNotification())
847 mode = rules()->checkShade( mode );
848 if( shade_mode == mode )
850 bool was_shade = isShade();
851 ShadeMode was_shade_mode = shade_mode;
853 if( was_shade == isShade())
855 if( decoration != NULL )
856 decoration->shadeChange();
860 if( shade_mode == ShadeNormal )
862 if ( isShown(
true ) && isOnCurrentDesktop())
863 Notify::raise( Notify::ShadeUp );
865 else if( shade_mode == ShadeNone )
867 if( isShown(
true ) && isOnCurrentDesktop())
868 Notify::raise( Notify::ShadeDown );
871 assert( decoration != NULL );
872 GeometryUpdatesPostponer blocker(
this );
874 decoration->borders( border_left, border_right, border_top, border_bottom );
876 int as = options->animateShade? 10 : 1;
882 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
885 shade_geometry_change =
true;
886 TQSize s( sizeForClientSize( TQSize( clientSize())));
887 s.setHeight( border_top + border_bottom );
888 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
889 XUnmapWindow( tqt_xdisplay(), wrapper );
890 XUnmapWindow( tqt_xdisplay(), client );
891 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
897 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
901 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
902 resizeDecoration( TQSize( s.width(), h ));
903 TQApplication::syncX();
904 }
while ( h > s.height() + step );
908 shade_geometry_change =
false;
911 if( was_shade_mode == ShadeHover )
912 workspace()->activateNextClient(
this );
914 workspace()->focusToNull();
918 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
923 shade_geometry_change =
true;
924 TQSize s( sizeForClientSize( clientSize()));
927 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
931 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
932 resizeDecoration( TQSize( s.width(), h ));
936 TQApplication::syncX();
937 }
while ( h < s.height() - step );
940 shade_geometry_change =
false;
942 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
944 XMapWindow( tqt_xdisplay(), wrapperId());
945 XMapWindow( tqt_xdisplay(), window());
946 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
947 if (options->shadowEnabled(
false))
949 for (ClientList::ConstIterator it = transients().begin();
950 it != transients().end(); ++it)
952 (*it)->removeShadow();
953 (*it)->drawDelayedShadow();
958 workspace()->requestFocus(
this );
960 checkMaximizeGeometry();
961 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
962 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
964 updateAllowedActions();
965 workspace()->updateMinimizedOfTransients(
this );
966 decoration->shadeChange();
970void Client::configureRequestTimeout()
972 inhibitConfigureRequests =
false;
973 sendSyntheticConfigureNotify();
976void Client::shadeHover()
978 setShade( ShadeHover );
982void Client::cancelShadeHover()
984 delete shadeHoverTimer;
988void Client::toggleShade()
991 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
994void Client::updateVisibility()
1001 setMappingState( IconicState );
1002 info->setState( NET::Hidden, NET::Hidden );
1003 setSkipTaskbar(
true,
false );
1009 setSkipTaskbar( original_skip_taskbar,
false );
1013 setMappingState( IconicState );
1014 info->setState( NET::Hidden, NET::Hidden );
1019 info->setState( 0, NET::Hidden );
1020 if( !isOnCurrentDesktop())
1022 setMappingState( IconicState );
1028 bool belongs_to_desktop =
false;
1029 for( ClientList::ConstIterator it = group()->members().begin();
1030 it != group()->members().end();
1032 if( (*it)->isDesktop())
1034 belongs_to_desktop =
true;
1037 if( !belongs_to_desktop && workspace()->showingDesktop())
1038 workspace()->resetShowingDesktop(
true );
1040 setMappingState( IconicState );
1042 setMappingState( NormalState );
1047void Client::setShadowed(
bool shadowed)
1051 wasShadowed = isShadowed();
1052 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1062 if (!activeOpacityCache.isNull())
1063 activeOpacityCache.resize(0);
1064 if (!inactiveOpacityCache.isNull())
1065 inactiveOpacityCache.resize(0);
1070void Client::updateOpacityCache()
1072 if (!activeOpacityCache.isNull())
1073 activeOpacityCache.resize(0);
1074 if (!inactiveOpacityCache.isNull())
1075 inactiveOpacityCache.resize(0);
1077 if (!moveResizeMode) {
1081 drawIntersectingShadows();
1082 if (options->shadowEnabled(isActive()))
1083 drawDelayedShadow();
1091void Client::drawIntersectingShadows() {
1095 TQValueList<Client *> reshadowClients;
1096 TQValueListIterator<ShadowRegion> it;
1097 TQValueListIterator<Client *> it2;
1099 if (!options->shadowEnabled(
false))
1104 region = shapeBoundingRegion;
1109 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1110 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1111 !(*it).region.intersect(region).isEmpty())
1112 reshadowClients.append((*it).client);
1115 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1117 (*it2)->removeShadow();
1118 (*it2)->drawDelayedShadow();
1127void Client::drawOverlappingShadows(
bool waitForMe)
1131 TQValueList<Client *> reshadowClients;
1132 ClientList stacking_order;
1133 ClientList::ConstIterator it;
1134 TQValueListIterator<ShadowRegion> it2;
1135 TQValueListIterator<Client *> it3;
1137 if (!options->shadowEnabled(
false))
1142 region = shapeBoundingRegion;
1144 stacking_order = workspace()->stackingOrder();
1145 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1151 while (it != stacking_order.end()) {
1152 if ((*it)->windowType() == NET::Dock) {
1163 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1164 if ((*it2).client == (*it)) {
1165 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1166 && !(*it2).region.intersect(region).isEmpty())
1167 reshadowClients.append((*it2).client);
1174 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1175 (*it3)->removeShadow();
1176 if (it3 == reshadowClients.begin()) {
1178 (*it3)->drawShadowAfter(
this);
1180 (*it3)->drawDelayedShadow();
1186 (*it3)->drawShadowAfter(aClient);
1195void Client::drawDelayedShadow()
1197 shadowDelayTimer->stop();
1198 shadowDelayTimer->start(SHADOW_DELAY,
true);
1204void Client::drawShadowAfter(Client *after)
1206 shadowAfterClient = after;
1207 connect(after, TQ_SIGNAL(shadowDrawn()), TQ_SLOT(drawShadow()));
1213void Client::drawShadow()
1217 int i, count, ordering;
1220 if (shadowAfterClient != NULL) {
1221 disconnect(shadowAfterClient, TQ_SIGNAL(shadowDrawn()),
this, TQ_SLOT(drawShadow()));
1222 shadowAfterClient = NULL;
1225 if (!isOnCurrentDesktop())
1232 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1236 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1238 shapeBoundingRegion = TQRegion();
1239 for (i = 0; i < count; i++) {
1241 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1243 shapeBoundingRegion += shapeRectangle;
1249 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1250 shapeBoundingRegion.translate(x(), y());
1253 if (!isShadowed() || hidden || isMinimized() ||
1254 maximizeMode() == MaximizeFull ||
1255 !options->shadowWindowType(windowType())) {
1267 TQMemArray<TQRgb> pixelData;
1268 TQPixmap shadowPixmap;
1270 TQRegion exposedRegion;
1271 ShadowRegion shadowRegion;
1272 int thickness, xOffset, yOffset;
1274 thickness = options->shadowThickness(isActive());
1275 xOffset = options->shadowXOffset(isActive());
1276 yOffset = options->shadowYOffset(isActive());
1277 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1279 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1280 width() + thickness * 2, height() + thickness * 2);
1281 shadowPixmap.resize(shadow.size());
1284 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1285 shadowWidget->setGeometry(shadow);
1286 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1287 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1288 shadowWidget->installEventFilter(
this);
1292 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1293 shadow.y(), shadow.width(), shadow.height(), thickness,
1295 shadowRegion.region = exposedRegion;
1296 shadowRegion.client =
this;
1297 shadowRegions.append(shadowRegion);
1299 if (opacityCache->isNull())
1300 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1301 exposedRegion, thickness,
1302 options->shadowOpacity(isActive()));
1304 imposeCachedShadow(shadowPixmap, exposedRegion);
1307 TQMemArray<TQRect> exposedRects;
1308 TQMemArray<TQRect>::Iterator it, itEnd;
1309 XRectangle *shadowShapes;
1311 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1312 shadow.y(), shadow.width(), shadow.height(), thickness,
1314 shadowRegion.region = exposedRegion;
1315 shadowRegion.client =
this;
1316 shadowRegions.append(shadowRegion);
1319 exposedRects = exposedRegion.rects();
1321 itEnd = exposedRects.end();
1322 shadowShapes =
new XRectangle[exposedRects.count()];
1323 for (it = exposedRects.begin(); it != itEnd; ++it) {
1324 shadowShapes[i].x = (*it).x();
1325 shadowShapes[i].y = (*it).y();
1326 shadowShapes[i].width = (*it).width();
1327 shadowShapes[i].height = (*it).height();
1330 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1331 ShapeBounding, -x() + thickness - xOffset,
1332 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1334 delete [] shadowShapes;
1336 if (opacityCache->isNull())
1337 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1338 exposedRegion, thickness,
1339 options->shadowOpacity(isActive()));
1341 imposeCachedShadow(shadowPixmap, exposedRegion);
1348 shadowWidget->setErasePixmap(shadowPixmap);
1353 ClientList stacking_order = workspace()->stackingOrder();
1354 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1355 if ((*it)->isDesktop())
1358 shadows[0] = (*it)->frameId();
1359 shadows[1] = shadowWidget->winId();
1363 shadows[0] = frameId();
1364 if (shadowWidget != NULL)
1365 shadows[1] = shadowWidget->winId();
1368 XRestackWindows(tqt_xdisplay(), shadows, 2);
1372 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1381void Client::removeShadow()
1383 TQValueList<ShadowRegion>::Iterator it;
1385 shadowDelayTimer->stop();
1387 if (shadowWidget != NULL) {
1388 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1389 if ((*it).client ==
this) {
1390 shadowRegions.remove(it);
1393 delete shadowWidget;
1394 shadowWidget = NULL;
1402TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1403 int h,
int thickness,
int xOffset,
int yOffset)
1405 TQRegion exposedRegion;
1407 exposedRegion = TQRegion(x, y, w, h);
1408 exposedRegion -= occludedRegion;
1410 if (thickness > 0) {
1413 TQMemArray<TQRect> occludedRects;
1414 TQMemArray<TQRect>::Iterator it, itEnd;
1415 TQRegion shadowRegion;
1417 occludedRects = occludedRegion.rects();
1418 itEnd = occludedRects.end();
1419 for (it = occludedRects.begin(); it != itEnd; ++it) {
1423 it->setTop(it->top() - thickness + yOffset);
1424 it->setLeft(it->left() - thickness + xOffset);
1425 it->setRight(it->right() + thickness + xOffset);
1426 it->setBottom(it->bottom() + thickness + yOffset);
1427 shadowRegion += TQRegion(*it);
1429 exposedRegion -= exposedRegion - shadowRegion;
1432 return exposedRegion;
1438void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1442 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1443 int subW, subH, w, x, y, zeroX, zeroY;
1445 TQMemArray<TQRect>::Iterator it, itEnd;
1446 TQMemArray<TQRect> rectangles;
1449 int thickness, windowX, windowY, xOffset, yOffset;
1451 rectangles = exposed.rects();
1452 rootWindow = tqt_xrootwin();
1453 thickness = options->shadowThickness(isActive());
1454 windowX = this->x();
1455 windowY = this->y();
1456 xOffset = options->shadowXOffset(isActive());
1457 yOffset = options->shadowYOffset(isActive());
1458 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1461 itEnd = rectangles.end();
1462 for (it = rectangles.begin(); it != itEnd; ++it) {
1463 subW = (*it).width();
1464 subH = (*it).height();
1465 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1467 zeroX = (*it).x() - windowX + thickness - xOffset;
1468 zeroY = (*it).y() - windowY + thickness - yOffset;
1469 image = subPixmap.convertToImage();
1471 for (x = 0; x < subW; x++) {
1472 for (y = 0; y < subH; y++) {
1473 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1474 pixel = image.pixel(x, y);
1475 pixelRed = tqRed(pixel);
1476 pixelGreen = tqGreen(pixel);
1477 pixelBlue = tqBlue(pixel);
1478 image.setPixel(x, y,
1479 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1480 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1481 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1485 subPixmap.convertFromImage(image);
1486 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1493void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1494 TQRegion exposed,
int thickness,
double maxOpacity)
1496 int distance, intersectCount, i, j, x, y;
1498 double decay, factor, opacity;
1499 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1500 int lineIntersects, maxIntersects, maxY;
1501 int irBottom, irLeft, irRight, irTop, yIncrement;
1502 int subW, subH, w, h, zeroX, zeroY;
1504 TQMemArray<TQRect>::Iterator it, itEnd;
1505 TQMemArray<TQRect> rectangles;
1508 int windowX, windowY, xOffset, yOffset;
1510 rectangles = exposed.rects();
1511 rootWindow = tqt_xrootwin();
1512 windowX = this->x();
1513 windowY = this->y();
1514 xOffset = options->shadowXOffset(isActive());
1515 yOffset = options->shadowYOffset(isActive());
1516 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1517 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1518 lineIntersects = thickness * 2 + 1;
1519 factor = maxIntersects / maxOpacity;
1520 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1522 h = pixmap.height();
1523 xOffset = options->shadowXOffset(isActive());
1524 yOffset = options->shadowYOffset(isActive());
1526 opacityCache->resize(0);
1527 opacityCache->resize(w * h);
1528 occluded.translate(-windowX + thickness, -windowY + thickness);
1530 itEnd = rectangles.end();
1531 for (it = rectangles.begin(); it != itEnd; ++it) {
1532 subW = (*it).width();
1533 subH = (*it).height();
1534 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1537 zeroX = (*it).x() - windowX + thickness - xOffset;
1538 zeroY = (*it).y() - windowY + thickness - yOffset;
1539 image = subPixmap.convertToImage();
1545 for (x = 0; x < subW; x++) {
1546 irLeft = zeroX + x - thickness;
1547 irRight = zeroX + x + thickness;
1552 irTop = zeroY + y - thickness * yIncrement;
1555 irBottom = zeroY + y + thickness * yIncrement;
1557 if (opacity == -1) {
1562 for (j = irTop; j != irBottom; j += yIncrement) {
1565 for (i = irLeft; i <= irRight; i++) {
1566 if (occluded.contains(TQPoint(i, j)))
1572 if (intersectCount < 0)
1575 for (i = irLeft; i <= irRight; i++) {
1576 if (occluded.contains(TQPoint(i, irBottom)))
1581 distance = maxIntersects - intersectCount;
1582 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1584 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1585 pixel = image.pixel(x, y);
1586 pixelRed = tqRed(pixel);
1587 pixelGreen = tqGreen(pixel);
1588 pixelBlue = tqBlue(pixel);
1589 image.setPixel(x, y,
1590 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1591 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1592 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1594 for (i = irLeft; i <= irRight; i++) {
1595 if (occluded.contains(TQPoint(i, irTop)))
1603 irTop += yIncrement;
1604 for (j = irTop; j != irBottom; j += yIncrement) {
1605 if (occluded.contains(TQPoint(irLeft, j)))
1609 for (j = irTop; j != irBottom; j += yIncrement) {
1610 if (occluded.contains(TQPoint(irRight, j)))
1623 subPixmap.convertFromImage(image);
1624 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1632void Client::setMappingState(
int s)
1634 assert( client != None );
1635 assert( !deleting || s == WithdrawnState );
1636 if( mapping_state == s )
1638 bool was_unmanaged = ( mapping_state == WithdrawnState );
1640 if( mapping_state == WithdrawnState )
1642 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1645 assert( s == NormalState || s == IconicState );
1647 unsigned long data[2];
1648 data[0] = (
unsigned long) s;
1649 data[1] = (
unsigned long) None;
1650 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1651 PropModeReplace, (
unsigned char *)data, 2);
1654 postponeGeometryUpdates(
false );
1661void Client::rawShow()
1663 if( decoration != NULL )
1664 decoration->widget()->show();
1665 XMapWindow( tqt_xdisplay(), frame );
1668 XMapWindow( tqt_xdisplay(), wrapper );
1669 XMapWindow( tqt_xdisplay(), client );
1671 if (options->shadowEnabled(isActive()))
1672 drawDelayedShadow();
1680void Client::rawHide()
1689 drawIntersectingShadows();
1690 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1691 XUnmapWindow( tqt_xdisplay(), frame );
1692 XUnmapWindow( tqt_xdisplay(), wrapper );
1693 XUnmapWindow( tqt_xdisplay(), client );
1694 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1695 if( decoration != NULL )
1696 decoration->widget()->hide();
1697 workspace()->clientHidden(
this );
1700void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1705 memset(&ev, 0,
sizeof(ev));
1706 ev.xclient.type = ClientMessage;
1707 ev.xclient.window = w;
1708 ev.xclient.message_type = a;
1709 ev.xclient.format = 32;
1710 ev.xclient.data.l[0] = protocol;
1711 ev.xclient.data.l[1] = get_tqt_x_time();
1712 ev.xclient.data.l[2] = data1;
1713 ev.xclient.data.l[3] = data2;
1714 ev.xclient.data.l[4] = data3;
1716 if (w == tqt_xrootwin())
1717 mask = SubstructureRedirectMask;
1718 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1724bool Client::isCloseable()
const
1726 if( isModalSystemNotification())
1728 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1741 if ( Pdeletewindow )
1743 Notify::raise( Notify::Close );
1744 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1761 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1764 Notify::raise( Notify::Close );
1767 Notify::raise( Notify::TransDelete );
1768 if( isNormalWindow())
1769 Notify::raise( Notify::Delete );
1770 killProcess(
false );
1772 XKillClient(tqt_xdisplay(), window() );
1779void Client::pingWindow()
1783 if( options->killPingTimeout == 0 )
1785 if( ping_timer != NULL )
1787 ping_timer =
new TQTimer(
this );
1788 connect( ping_timer, TQ_SIGNAL( timeout()), TQ_SLOT( pingTimeout()));
1789 ping_timer->start( options->killPingTimeout,
true );
1790 ping_timestamp = get_tqt_x_time();
1791 workspace()->sendPingToWindow( window(), ping_timestamp );
1794void Client::gotPing( Time timestamp )
1797 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1801 if( process_killer != NULL )
1803 process_killer->kill();
1804 delete process_killer;
1805 process_killer = NULL;
1809void Client::pingTimeout()
1811 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1814 killProcess(
true, ping_timestamp );
1817void Client::killProcess(
bool ask, Time timestamp )
1819 if( process_killer != NULL )
1821 Q_ASSERT( !ask || timestamp != CurrentTime );
1823 pid_t pid = info->pid();
1824 if( pid <= 0 || machine.isEmpty())
1826 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1829 if( machine !=
"localhost" )
1832 proc <<
"xon" << machine <<
"kill" << pid;
1833 proc.start( TDEProcess::DontCare );
1836 ::kill( pid, SIGTERM );
1840 process_killer =
new TDEProcess(
this );
1841 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1842 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1843 <<
"--windowname" <<
caption().utf8()
1844 <<
"--applicationname" << resourceClass()
1845 <<
"--wid" << TQCString().setNum( window())
1846 <<
"--timestamp" << TQCString().setNum( timestamp );
1847 connect( process_killer, TQ_SIGNAL( processExited( TDEProcess* )),
1848 TQ_SLOT( processKillerExited()));
1849 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1851 delete process_killer;
1852 process_killer = NULL;
1858bool Client::isSuspendable()
const
1860 bool cansuspend =
true;
1861 if( skipTaskbar() || skipPager() )
1864 pid_t pid = info->pid();
1865 if( pid <= 0 || machine.isEmpty())
1867 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1868 if( machine !=
"localhost" )
1875 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1877 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1879 if (procStatFile.open(IO_ReadOnly))
1881 TQByteArray statRaw = procStatFile.readAll();
1882 procStatFile.close();
1884 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1885 char tbuf[PATH_MAX];
1887 TQString state(TQChar(inf->pr_sname));
1889 readlink(TQString(
"/proc/%1/path/a.out").arg(pid).latin1(),
1890 tbuf,
sizeof(tbuf));
1891 tcomm = basename(tbuf);
1893 TQString statString(statRaw);
1894 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1895 TQString tcomm = statFields[1];
1896 TQString state = statFields[2];
1901 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1903 Client* nextclient = *it;
1904 pid_t nextpid = nextclient->info->pid();
1905 TQCString nextmachine = nextclient->wmClientMachine(
true );
1906 if( nextpid > 0 && (!nextmachine.isEmpty()))
1908 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1910 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1916 TQString execname(tcomm);
1917 execname.truncate(execname.length()-1);
1918 execname = execname.remove(0,1);
1920 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1937bool Client::isResumeable()
const
1940 pid_t pid = info->pid();
1941 if( pid <= 0 || machine.isEmpty())
1943 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1944 if( machine !=
"localhost" )
1951 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1953 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1955 if (procStatFile.open(IO_ReadOnly))
1957 TQByteArray statRaw = procStatFile.readAll();
1958 procStatFile.close();
1960 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1961 TQString state(TQChar(inf->pr_sname));
1963 TQString statString(statRaw);
1964 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1965 TQString tcomm = statFields[1];
1966 TQString state = statFields[2];
1984bool Client::queryUserSuspendedResume()
1988 if (process_resumer != NULL)
1993 process_resumer =
new TDEProcess(
this );
1994 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
1995 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
1996 <<
"--windowname" <<
caption().utf8()
1997 <<
"--applicationname" << resourceClass()
1998 <<
"--wid" << TQCString().setNum( window());
1999 connect( process_resumer, TQ_SIGNAL( processExited( TDEProcess* )),
2000 TQ_SLOT( processResumerExited()));
2001 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
2003 delete process_resumer;
2004 process_resumer = NULL;
2015void Client::suspendWindow()
2018 pid_t pid = info->pid();
2019 if( pid <= 0 || machine.isEmpty())
2021 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
2022 if( machine !=
"localhost" )
2028 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2030 Client* nextclient = *it;
2031 pid_t nextpid = nextclient->info->pid();
2032 TQCString nextmachine = nextclient->wmClientMachine(
true );
2033 if( nextpid > 0 && (!nextmachine.isEmpty()))
2035 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2037 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2038 nextclient->info->setVisibleName(newCaption.utf8());
2039 nextclient->info->setVisibleIconName(newCaption.utf8());
2040 nextclient->minimized_before_suspend = nextclient->isMinimized();
2041 nextclient->minimize(
true);
2045 ::kill( pid, SIGSTOP );
2049void Client::resumeWindow()
2052 pid_t pid = info->pid();
2053 if( pid <= 0 || machine.isEmpty())
2055 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2056 if( machine !=
"localhost" )
2062 ::kill( pid, SIGCONT );
2063 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2065 Client* nextclient = *it;
2066 pid_t nextpid = nextclient->info->pid();
2067 TQCString nextmachine = nextclient->wmClientMachine(
true );
2068 if( nextpid > 0 && (!nextmachine.isEmpty()))
2070 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2072 if (!nextclient->minimized_before_suspend)
2074 nextclient->unminimize(
true);
2076 nextclient->updateCaption();
2083void Client::processKillerExited()
2085 kdDebug( 1212 ) <<
"Killer exited" << endl;
2086 delete process_killer;
2087 process_killer = NULL;
2090void Client::processResumerExited()
2092 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2094 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2097 takeFocus( Allowed );
2099 delete process_resumer;
2100 process_resumer = NULL;
2103void Client::setSkipTaskbar(
bool b,
bool from_outside )
2105 int was_wants_tab_focus = wantsTabFocus();
2108 b = rules()->checkSkipTaskbar( b );
2109 original_skip_taskbar = b;
2111 if ( b == skipTaskbar() )
2114 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2115 updateWindowRules();
2116 if( was_wants_tab_focus != wantsTabFocus())
2117 workspace()->updateFocusChains(
this,
2118 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2121void Client::setSkipPager(
bool b )
2123 b = rules()->checkSkipPager( b );
2124 if ( b == skipPager() )
2127 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2128 updateWindowRules();
2131void Client::setModal(
bool m )
2142void Client::setDesktop(
int desktop )
2144 if(
desktop != NET::OnAllDesktops )
2145 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(),
desktop ));
2149 int was_desk = desk;
2152 if(( was_desk == NET::OnAllDesktops ) != (
desktop == NET::OnAllDesktops ))
2154 if ( isShown(
true ))
2155 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2156 workspace()->updateOnAllDesktopsOfTransients(
this );
2158 if( decoration != NULL )
2159 decoration->desktopChange();
2160 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2162 updateWindowRules();
2165void Client::setOnAllDesktops(
bool b )
2167 if(( b && isOnAllDesktops())
2168 || ( !b && !isOnAllDesktops()))
2171 setDesktop( NET::OnAllDesktops );
2173 setDesktop( workspace()->currentDesktop());
2176bool Client::isOnCurrentDesktop()
const
2178 return isOnDesktop( workspace()->currentDesktop());
2181int Client::screen()
const
2183 if( !options->xineramaEnabled )
2185 return workspace()->screenNumber( geometry().center());
2188bool Client::isOnScreen(
int screen )
const
2190 if( !options->xineramaEnabled )
2192 return workspace()->screenGeometry( screen ).intersects( geometry());
2196void Client::takeActivity(
int flags,
bool handled, allowed_t )
2198 if( !handled || !Ptakeactivity )
2200 if( flags & ActivityFocus )
2201 takeFocus( Allowed );
2202 if( flags & ActivityRaise )
2203 workspace()->raiseClient(
this );
2208 static Time previous_activity_timestamp;
2209 static Client* previous_client;
2210 if( previous_activity_timestamp == get_tqt_x_time() && previous_client !=
this )
2212 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2213 kdDebug( 1212 ) << kdBacktrace() << endl;
2215 previous_activity_timestamp = get_tqt_x_time();
2216 previous_client =
this;
2218 workspace()->sendTakeActivity(
this, get_tqt_x_time(), flags );
2222void Client::takeFocus( allowed_t )
2225 static Time previous_focus_timestamp;
2226 static Client* previous_client;
2227 if( previous_focus_timestamp == get_tqt_x_time() && previous_client !=
this )
2229 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2230 kdDebug( 1212 ) << kdBacktrace() << endl;
2232 previous_focus_timestamp = get_tqt_x_time();
2233 previous_client =
this;
2235 if ( rules()->checkAcceptFocus( input ))
2237 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, get_tqt_x_time() );
2241 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2243 workspace()->setShouldGetFocus(
this );
2255 if (isModalSystemNotification())
2257 return Pcontexthelp;
2271 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2272 TQWhatsThis::enterWhatsThisMode();
2281void Client::fetchName()
2283 setCaption( readName());
2286TQString Client::readName()
const
2288 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2289 return TQString::fromUtf8( info->name() );
2291 return KWin::readNameProperty( window(), XA_WM_NAME );
2294KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2296void Client::setCaption(
const TQString& s,
bool force )
2298 if ( s != cap_normal || force )
2300 bool reset_name = force;
2301 for(
unsigned int i = 0;
2304 if( !s[ i ].isPrint())
2307 bool was_suffix = ( !cap_suffix.isEmpty());
2308 TQString machine_suffix;
2311 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2312 cap_suffix = machine_suffix + shortcut_suffix;
2313 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2318 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2320 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2321 info->setVisibleName(
caption().utf8() );
2324 if(( (was_suffix && cap_suffix.isEmpty())
2327 info->setVisibleName(
"" );
2328 info->setVisibleIconName(
"" );
2330 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2331 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2333 if( isManaged() && decoration != NULL )
2334 decoration->captionChange();
2338void Client::updateCaption()
2340 setCaption( cap_normal,
true );
2343void Client::fetchIconicName()
2346 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2347 s = TQString::fromUtf8( info->iconName() );
2349 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2350 if ( s != cap_iconic )
2352 bool was_set = !cap_iconic.isEmpty();
2354 if( !cap_suffix.isEmpty())
2356 if( !cap_iconic.isEmpty())
2357 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2359 info->setVisibleIconName(
"" );
2368 return full ? cap_normal + cap_suffix : cap_normal;
2371void Client::getWMHints()
2373 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2375 window_group = None;
2379 if( hints->flags & InputHint )
2380 input = hints->input;
2381 if( hints->flags & WindowGroupHint )
2382 window_group = hints->window_group;
2383 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2384 XFree( (
char*)hints );
2388 updateAllowedActions();
2391void Client::getMotifHints()
2393 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2394 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2395 motif_noborder = mnoborder;
2396 if( !hasNETSupport())
2398 motif_may_resize = mresize;
2399 motif_may_move = mmove;
2402 motif_may_resize = motif_may_move =
true;
2405 motif_may_close = mclose;
2407 updateDecoration(
true );
2410void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2414 *icon = KWin::icon( win, 32, 32,
true, KWin::NETWM | KWin::WMHints );
2415 if( miniicon != NULL )
2417 if( icon == NULL || !icon->isNull())
2418 *miniicon = KWin::icon( win, 16, 16,
true, KWin::NETWM | KWin::WMHints );
2420 *miniicon = TQPixmap();
2424void Client::getIcons()
2427 readIcons( window(), &icon_pix, &miniicon_pix );
2428 if( icon_pix.isNull())
2430 icon_pix = group()->icon();
2431 miniicon_pix = group()->miniIcon();
2433 if( icon_pix.isNull() && isTransient())
2435 ClientList mainclients = mainClients();
2436 for( ClientList::ConstIterator it = mainclients.begin();
2437 it != mainclients.end() && icon_pix.isNull();
2440 icon_pix = (*it)->icon();
2441 miniicon_pix = (*it)->miniIcon();
2444 if( icon_pix.isNull())
2446 icon_pix = KWin::icon( window(), 32, 32,
true, KWin::ClassHint | KWin::XApp );
2447 miniicon_pix = KWin::icon( window(), 16, 16,
true, KWin::ClassHint | KWin::XApp );
2449 if( isManaged() && decoration != NULL )
2450 decoration->iconChange();
2453void Client::getWindowProtocols()
2464 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2466 for (i = 0; i < n; i++)
2467 if (p[i] == atoms->wm_delete_window)
2469 else if (p[i] == atoms->wm_take_focus)
2471 else if (p[i] == atoms->net_wm_take_activity)
2473 else if (p[i] == atoms->net_wm_context_help)
2475 else if (p[i] == atoms->net_wm_ping)
2482static int nullErrorHandler(Display *, XErrorEvent *)
2492 return getStringProperty(w, tqt_window_role).lower();
2500 return getStringProperty(w, tqt_sm_client_id);
2508 return getStringProperty(w, XA_WM_COMMAND,
' ');
2518 unsigned long nitems = 0;
2519 unsigned long extra = 0;
2520 unsigned char *data = 0;
2522 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2523 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2524 False, XA_WINDOW, &type, &format,
2525 &nitems, &extra, &data );
2526 XSetErrorHandler(oldHandler);
2527 if (status == Success )
2529 if (data && nitems > 0)
2530 result = *((Window*) data);
2537void Client::getWmClientLeader()
2549 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2561 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2566void Client::getWmClientMachine()
2568 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2569 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2570 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2571 if( client_machine.isEmpty())
2572 client_machine =
"localhost";
2581 TQCString result = client_machine;
2584 if( result !=
"localhost" && isLocalMachine( result ))
2585 result =
"localhost";
2596 if (wmClientLeaderWin)
2597 return wmClientLeaderWin;
2601bool Client::wantsTabFocus()
const
2603 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2607bool Client::wantsInput()
const
2609 return rules()->checkAcceptFocus( input || Ptakefocus );
2612bool Client::isDesktop()
const
2614 return windowType() == NET::Desktop;
2617bool Client::isDock()
const
2619 return windowType() == NET::Dock;
2622bool Client::isTopMenu()
const
2624 return windowType() == NET::TopMenu;
2628bool Client::isMenu()
const
2630 return windowType() == NET::Menu && !isTopMenu();
2633bool Client::isToolbar()
const
2635 return windowType() == NET::Toolbar;
2638bool Client::isSplash()
const
2640 return windowType() == NET::Splash;
2643bool Client::isUtility()
const
2645 return windowType() == NET::Utility;
2648bool Client::isDialog()
const
2650 return windowType() == NET::Dialog;
2653bool Client::isNormalWindow()
const
2655 return windowType() == NET::Normal;
2658bool Client::isSpecialWindow()
const
2660 return isDesktop() || isDock() || isSplash() || isTopMenu()
2664NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2666 NET::WindowType wt = info->windowType( supported_types );
2669 NET::WindowType wt2 = rules()->checkType( wt );
2673 info->setWindowType( wt );
2676 if( wt == NET::Menu )
2681 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2682 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2686 const char*
const oo_prefix =
"openoffice.org";
2688 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2690 if( wt == NET::Unknown )
2691 wt = isTransient() ? NET::Dialog : NET::Normal;
2699void Client::setCursor( Position m )
2707 case PositionTopLeft:
2708 case PositionBottomRight:
2709 setCursor( TQt::sizeFDiagCursor );
2711 case PositionBottomLeft:
2712 case PositionTopRight:
2713 setCursor( TQt::sizeBDiagCursor );
2716 case PositionBottom:
2717 setCursor( TQt::sizeVerCursor );
2721 setCursor( TQt::sizeHorCursor );
2725 setCursor( TQt::sizeAllCursor );
2727 setCursor( TQt::arrowCursor );
2734void Client::setCursor(
const TQCursor& c )
2736 if( c.handle() == cursor.handle())
2739 if( decoration != NULL )
2740 decoration->widget()->setCursor( cursor );
2741 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2744Client::Position Client::mousePosition(
const TQPoint& p )
const
2746 if( decoration != NULL )
2747 return decoration->mousePosition( p );
2748 return PositionCenter;
2751void Client::updateAllowedActions(
bool force )
2753 if( !isManaged() && !force )
2755 unsigned long old_allowed_actions = allowed_actions;
2756 allowed_actions = 0;
2758 allowed_actions |= NET::ActionMove;
2760 allowed_actions |= NET::ActionResize;
2762 allowed_actions |= NET::ActionMinimize;
2764 allowed_actions |= NET::ActionShade;
2766 if( isMaximizable())
2767 allowed_actions |= NET::ActionMax;
2768 if( userCanSetFullScreen())
2769 allowed_actions |= NET::ActionFullScreen;
2770 allowed_actions |= NET::ActionChangeDesktop;
2772 allowed_actions |= NET::ActionClose;
2773 if( old_allowed_actions == allowed_actions )
2776 info->setAllowedActions( allowed_actions );
2780void Client::autoRaise()
2782 workspace()->raiseClient(
this );
2786void Client::cancelAutoRaise()
2788 delete autoRaiseTimer;
2792void Client::setOpacity(uint opacity)
2797 if (opacity == Opacity::Opaque && !custom_opacity)
2799 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2800 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2803 if(opacity == opacity_)
2805 long data = opacity;
2806 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2807 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2812void Client::setShadowSize(uint shadowSize)
2816 long data = shadowSize;
2817 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2820uint Client::defaultOpacity()
2822 return defaultOpacity(isActive() || (
keepAbove() && options->keepAboveAsActive));
2825uint Client::defaultOpacity(
bool active)
2829 if( ruleOpacityActive() )
2830 return rule_opacity_active;
2832 return options->translucentActiveWindows ? options->activeWindowOpacity : Opacity::Opaque;
2836 if( ruleOpacityInactive() )
2837 return rule_opacity_inactive;
2839 return options->translucentInactiveWindows ? options->inactiveWindowOpacity : Opacity::Opaque;
2843void Client::updateOpacity()
2846 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2848 uint opacity = defaultOpacity();
2849 setOpacity(opacity);
2854 ClientList tmpGroupMembers = group()->members();
2855 ClientList groupMembers;
2856 groupMembers.append(
this);
2857 tmpGroupMembers.remove(
this);
2858 ClientList::Iterator it = tmpGroupMembers.begin();
2859 while (it != tmpGroupMembers.end())
2862 if ((*it) !=
this && (*it)->isBMP())
2866 if ((*it)->touches(
this))
2869 (*it)->setOpacity(opacity);
2871 (*it)->setShadowSize(options->activeWindowShadowSize);
2872 groupMembers.append(*it);
2873 tmpGroupMembers.remove(it);
2874 it = tmpGroupMembers.begin();
2880 for( ClientList::ConstIterator it2 = groupMembers.begin(); it2 != groupMembers.end(); it2++ )
2882 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2885 (*it)->setOpacity(opacity);
2886 (*it)->setShadowSize(isActive() ? options->activeWindowShadowSize : options->inactiveWindowShadowSize);
2887 groupMembers.append(*it);
2888 tmpGroupMembers.remove(it);
2889 it = tmpGroupMembers.begin();
2895 if (found)
continue;
2901 else if (isNormalWindow())
2904 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2905 if ((*it)->isUtility() || ((*it)->isDialog() && isActive() ))
2906 (*it)->setOpacity(opacity);
2910void Client::updateShadowSize()
2913 if (!(isNormalWindow() || isDialog() || isUtility() ))
2916 setShadowSize(options->activeWindowShadowSize);
2918 setShadowSize(options->inactiveWindowShadowSize);
2921uint Client::ruleOpacityInactive()
2923 return rule_opacity_inactive;
2926uint Client::ruleOpacityActive()
2928 return rule_opacity_active;
2931bool Client::getWindowOpacity()
2933 unsigned char *data = 0;
2936 unsigned long n, left;
2937 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
2938 if (result == Success && data && format == 32 )
2940 opacity_ = *
reinterpret_cast< long*
>( data );
2944 if ( !(Workspace::self()->initializing()
2945 && ( opacity_ == defaultOpacity(
false)
2946 || opacity_ == defaultOpacity(
true) ) ) )
2948 custom_opacity =
true;
2951 XFree ((
char*)data);
2957void Client::setCustomOpacityFlag(
bool custom)
2959 custom_opacity = custom;
2962uint Client::opacity()
2967int Client::opacityPercentage()
2969 return opacity_ / ( 0xffffffff / 100 );
2972bool Client::touches(
const Client* c)
2975 if (y() == c->y() + c->height())
2977 if (y() + height() == c->y())
2979 if (x() == c->x() + c->width())
2981 if (x() + width() == c->x())
2987kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
2990 return stream <<
"\'NULL_CLIENT\'";
2991 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
2993kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
2997 for( ClientList::ConstIterator it = list.begin();
3009kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3013 for( ConstClientList::ConstIterator it = list.begin();
3027TQPixmap * twin_get_menu_pix_hack()
3031 p = SmallIcon(
"bx2" );
3037#include "client.moc"
static Window staticWmClientLeader(WId)
bool providesContextHelp() const
void setActive(bool, bool updateOpacity=true)
bool isMinimizable() const
void minimize(bool avoid_animation=false)
static TQCString staticSessionId(WId)
TQCString wmClientMachine(bool use_localhost) const
static TQCString staticWindowRole(WId)
static TQCString staticWmCommand(WId)
void updateUserTime(Time time=CurrentTime)
bool isOnDesktop(int d) const
void releaseWindow(bool on_shutdown=false)
Window wmClientLeader() const
TQString caption(bool full=true) const
void move(int x, int y, ForceGeometry_t force=NormalGeometrySet)