16 #include <tqapplication.h>
17 #include <tqpainter.h>
18 #include <tqdatetime.h>
21 #include <tdeprocess.h>
23 #include <kstandarddirs.h>
24 #include <tqwhatsthis.h>
26 #include <kiconloader.h>
27 #include <tdelocale.h>
37 #include "workspace.h"
39 #include "notifications.h"
42 #include <X11/extensions/shape.h>
47 extern Atom tqt_wm_state;
48 extern Atom tqt_window_role;
49 extern Atom tqt_sm_client_id;
52 static const int SHADOW_DELAY = 200;
54 namespace KWinInternal
68 static 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 ),
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 );
213 void Client::deleteClient( Client* c, allowed_t )
225 workspace()->discardUsedWindowRules(
this,
true );
226 StackingUpdatesBlocker blocker( workspace());
227 if (!custom_opacity) setOpacity(FALSE);
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 );
284 void 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 );
312 void 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 options->onlyDecoTranslucent ?
332 setDecoHashProperty(border_top, border_right, border_bottom, border_left):
333 unsetDecoHashProperty();
334 int save_workarea_diff_x = workarea_diff_x;
335 int save_workarea_diff_y = workarea_diff_y;
336 move( calculateGravitation(
false ));
337 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
338 workarea_diff_x = save_workarea_diff_x;
339 workarea_diff_y = save_workarea_diff_y;
344 if( check_workspace_pos )
345 checkWorkspacePosition();
346 postponeGeometryUpdates(
false );
348 decoration->widget()->show();
349 updateFrameExtents();
350 updateOpacityCache();
353 void Client::destroyDecoration()
355 if( decoration != NULL )
359 TQPoint grav = calculateGravitation(
true );
360 border_left = border_right = border_top = border_bottom = 0;
361 setMask( TQRegion());
362 int save_workarea_diff_x = workarea_diff_x;
363 int save_workarea_diff_y = workarea_diff_y;
364 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
366 workarea_diff_x = save_workarea_diff_x;
367 workarea_diff_y = save_workarea_diff_y;
371 void Client::checkBorderSizes()
373 if( decoration == NULL )
375 int new_left, new_right, new_top, new_bottom;
376 decoration->borders( new_left, new_right, new_top, new_bottom );
377 if( new_left == border_left && new_right == border_right
378 && new_top == border_top && new_bottom == border_bottom )
380 GeometryUpdatesPostponer blocker(
this );
381 move( calculateGravitation(
true ));
382 border_left = new_left;
383 border_right = new_right;
384 border_top = new_top;
385 border_bottom = new_bottom;
386 if (border_left != new_left ||
387 border_right != new_right ||
388 border_top != new_top ||
389 border_bottom != new_bottom)
390 options->onlyDecoTranslucent ?
391 setDecoHashProperty(new_top, new_right, new_bottom, new_left):
392 unsetDecoHashProperty();
393 move( calculateGravitation(
false ));
394 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
395 checkWorkspacePosition();
398 void Client::detectNoBorder()
400 if( Shape::hasShape( window()))
405 switch( windowType())
427 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
431 void Client::detectShapable()
433 if( Shape::hasShape( window()))
435 switch( windowType())
455 void Client::updateFrameExtents()
458 strut.left = border_left;
459 strut.right = border_right;
460 strut.top = border_top;
461 strut.bottom = border_bottom;
462 info->setFrameExtents( strut );
470 void Client::resizeDecoration(
const TQSize& s )
472 if( decoration == NULL )
474 TQSize oldsize = decoration->widget()->size();
475 decoration->resize( s );
478 TQResizeEvent e( s, oldsize );
479 TQApplication::sendEvent( decoration->widget(), &e );
481 if (!moveResizeMode && options->shadowEnabled(isActive()))
485 updateOpacityCache();
489 bool Client::noBorder()
const
491 return noborder || isFullScreen() || user_noborder || motif_noborder;
494 bool Client::userCanSetNoBorder()
const
496 return !noborder && !isFullScreen() && !isShade();
499 bool Client::isUserNoBorder()
const
501 return user_noborder;
504 void Client::setUserNoBorder(
bool set )
506 if( !userCanSetNoBorder())
508 set = rules()->checkNoBorder( set );
509 if( user_noborder == set )
512 updateDecoration(
true,
false );
516 bool Client::isModalSystemNotification()
const
518 unsigned char *data = 0;
521 unsigned long n, left;
522 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
523 if (result == Success && data && format == 32 )
530 void Client::updateShape()
533 if( shape() && !noBorder())
536 updateDecoration(
true );
538 updateOpacityCache();
541 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
542 clientPos().x(), clientPos().y(),
543 window(), ShapeBounding, ShapeSet);
549 if( Shape::version() >= 0x11 )
559 static Window helper_window = None;
560 if( helper_window == None )
561 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
562 0, 0, 1, 1, 0, 0, 0 );
563 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
564 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
565 frameId(), ShapeBounding, ShapeSet );
566 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
567 clientPos().x(), clientPos().y(),
568 window(), ShapeBounding, ShapeSubtract );
569 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
570 clientPos().x(), clientPos().y(),
571 window(), ShapeInput, ShapeUnion );
572 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
573 helper_window, ShapeInput, ShapeSet );
577 void Client::setMask(
const TQRegion& reg,
int mode )
581 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
583 else if( mode == X::Unsorted )
584 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
585 reg.handle(), ShapeSet );
588 TQMemArray< TQRect > rects = reg.rects();
589 XRectangle* xrects =
new XRectangle[ rects.count() ];
590 for(
unsigned int i = 0;
594 xrects[ i ].x = rects[ i ].x();
595 xrects[ i ].y = rects[ i ].y();
596 xrects[ i ].width = rects[ i ].width();
597 xrects[ i ].height = rects[ i ].height();
599 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
600 xrects, rects.count(), ShapeSet, mode );
606 TQRegion Client::mask()
const
609 return TQRegion( 0, 0, width(), height());
613 void Client::setShapable(
bool b)
616 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
619 void Client::hideClient(
bool hide )
632 if( isSpecialWindow())
634 if( isModalSystemNotification())
638 bool shown_mainwindow =
false;
639 ClientList mainclients = mainClients();
640 for( ClientList::ConstIterator it = mainclients.begin();
641 it != mainclients.end();
644 if( (*it)->isShown(
true ))
645 shown_mainwindow =
true;
647 if( !shown_mainwindow )
653 if( transientFor() != NULL )
655 if( !wantsTabFocus())
665 if( isModalSystemNotification())
679 info->setState(0, NET::Shaded);
681 Notify::raise( Notify::Minimize );
684 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
685 animateMinimizeOrUnminimize(
true );
690 updateAllowedActions();
691 workspace()->updateMinimizedOfTransients(
this );
693 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
696 void Client::unminimize(
bool avoid_animation )
698 if (!queryUserSuspendedResume())
705 info->setState(NET::Shaded, NET::Shaded);
707 Notify::raise( Notify::UnMinimize );
709 if( isOnCurrentDesktop() && isShown(
true ))
711 if( mainClients().isEmpty() && !avoid_animation )
712 animateMinimizeOrUnminimize( FALSE );
715 updateAllowedActions();
716 workspace()->updateMinimizedOfTransients(
this );
720 extern bool blockAnimation;
722 void Client::animateMinimizeOrUnminimize(
bool minimize )
724 if ( blockAnimation )
726 if ( !options->animateMinimize )
729 if( decoration != NULL && decoration->animateMinimize(
minimize ))
736 float lf,rf,tf,bf,step;
738 int speed = options->animateMinimizeSpeed;
744 step = 40. * (11 - speed );
746 NETRect r = info->iconGeometry();
747 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
748 if ( !icongeom.isValid() )
751 TQPixmap pm = animationPixmap(
minimize ? width() : icongeom.width() );
753 TQRect before, after;
756 before = TQRect( x(), y(), width(), pm.height() );
757 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
761 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
762 after = TQRect( x(), y(), width(), pm.height() );
765 lf = (after.left() - before.left())/step;
766 rf = (after.right() - before.right())/step;
767 tf = (after.top() - before.top())/step;
768 bf = (after.bottom() - before.bottom())/step;
772 TQRect area = before;
780 TQPainter p ( workspace()->desktopWidget() );
781 bool need_to_clear = FALSE;
787 pm = animationPixmap( area.width() );
788 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
789 p.drawPixmap( area.x(), area.y(), pm );
792 p.drawPixmap( area2.x(), area2.y(), pm3 );
793 need_to_clear = FALSE;
797 XFlush(tqt_xdisplay());
798 XSync( tqt_xdisplay(), FALSE );
802 area.setLeft(before.left() +
int(diff*lf));
803 area.setRight(before.right() +
int(diff*rf));
804 area.setTop(before.top() +
int(diff*tf));
805 area.setBottom(before.bottom() +
int(diff*bf));
808 if ( area2.intersects( area ) )
809 p.drawPixmap( area2.x(), area2.y(), pm2 );
813 need_to_clear = TRUE;
816 }
while ( t.elapsed() < step);
817 if (area2 == area || need_to_clear )
818 p.drawPixmap( area2.x(), area2.y(), pm2 );
828 TQPixmap Client::animationPixmap(
int w )
830 TQFont font = options->font(isActive());
831 TQFontMetrics fm( font );
832 TQPixmap pm( w, fm.lineSpacing() );
833 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
835 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
836 p.setFont(options->font(isActive()));
837 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
842 bool Client::isShadeable()
const
844 return !isSpecialWindow() && !noBorder();
847 void Client::setShade( ShadeMode mode )
851 if( isModalSystemNotification())
853 mode = rules()->checkShade( mode );
854 if( shade_mode == mode )
856 bool was_shade = isShade();
857 ShadeMode was_shade_mode = shade_mode;
859 if( was_shade == isShade())
861 if( decoration != NULL )
862 decoration->shadeChange();
866 if( shade_mode == ShadeNormal )
868 if ( isShown(
true ) && isOnCurrentDesktop())
869 Notify::raise( Notify::ShadeUp );
871 else if( shade_mode == ShadeNone )
873 if( isShown(
true ) && isOnCurrentDesktop())
874 Notify::raise( Notify::ShadeDown );
877 assert( decoration != NULL );
878 GeometryUpdatesPostponer blocker(
this );
880 decoration->borders( border_left, border_right, border_top, border_bottom );
882 int as = options->animateShade? 10 : 1;
888 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
891 shade_geometry_change =
true;
892 TQSize s( sizeForClientSize( TQSize( clientSize())));
893 s.setHeight( border_top + border_bottom );
894 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
895 XUnmapWindow( tqt_xdisplay(), wrapper );
896 XUnmapWindow( tqt_xdisplay(), client );
897 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
903 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
907 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
908 resizeDecoration( TQSize( s.width(), h ));
909 TQApplication::syncX();
910 }
while ( h > s.height() + step );
914 shade_geometry_change =
false;
917 if( was_shade_mode == ShadeHover )
918 workspace()->activateNextClient(
this );
920 workspace()->focusToNull();
924 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
929 shade_geometry_change =
true;
930 TQSize s( sizeForClientSize( clientSize()));
933 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
937 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
938 resizeDecoration( TQSize( s.width(), h ));
942 TQApplication::syncX();
943 }
while ( h < s.height() - step );
946 shade_geometry_change =
false;
948 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
950 XMapWindow( tqt_xdisplay(), wrapperId());
951 XMapWindow( tqt_xdisplay(), window());
952 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
953 if (options->shadowEnabled(
false))
955 for (ClientList::ConstIterator it = transients().begin();
956 it != transients().end(); ++it)
958 (*it)->removeShadow();
959 (*it)->drawDelayedShadow();
964 workspace()->requestFocus(
this );
966 checkMaximizeGeometry();
967 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
968 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
970 updateAllowedActions();
971 workspace()->updateMinimizedOfTransients(
this );
972 decoration->shadeChange();
976 void Client::configureRequestTimeout()
978 inhibitConfigureRequests =
false;
979 sendSyntheticConfigureNotify();
982 void Client::shadeHover()
984 setShade( ShadeHover );
988 void Client::cancelShadeHover()
990 delete shadeHoverTimer;
994 void Client::toggleShade()
997 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
1000 void Client::updateVisibility()
1007 setMappingState( IconicState );
1008 info->setState( NET::Hidden, NET::Hidden );
1009 setSkipTaskbar(
true,
false );
1015 setSkipTaskbar( original_skip_taskbar,
false );
1019 setMappingState( IconicState );
1020 info->setState( NET::Hidden, NET::Hidden );
1025 info->setState( 0, NET::Hidden );
1026 if( !isOnCurrentDesktop())
1028 setMappingState( IconicState );
1034 bool belongs_to_desktop =
false;
1035 for( ClientList::ConstIterator it = group()->members().begin();
1036 it != group()->members().end();
1038 if( (*it)->isDesktop())
1040 belongs_to_desktop =
true;
1043 if( !belongs_to_desktop && workspace()->showingDesktop())
1044 workspace()->resetShowingDesktop(
true );
1046 setMappingState( IconicState );
1048 setMappingState( NormalState );
1053 void Client::setShadowed(
bool shadowed)
1057 wasShadowed = isShadowed();
1058 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1068 if (!activeOpacityCache.isNull())
1069 activeOpacityCache.resize(0);
1070 if (!inactiveOpacityCache.isNull())
1071 inactiveOpacityCache.resize(0);
1076 void Client::updateOpacityCache()
1078 if (!activeOpacityCache.isNull())
1079 activeOpacityCache.resize(0);
1080 if (!inactiveOpacityCache.isNull())
1081 inactiveOpacityCache.resize(0);
1083 if (!moveResizeMode) {
1087 drawIntersectingShadows();
1088 if (options->shadowEnabled(isActive()))
1089 drawDelayedShadow();
1097 void Client::drawIntersectingShadows() {
1101 TQValueList<Client *> reshadowClients;
1102 TQValueListIterator<ShadowRegion> it;
1103 TQValueListIterator<Client *> it2;
1105 if (!options->shadowEnabled(
false))
1110 region = shapeBoundingRegion;
1115 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1116 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1117 !(*it).region.intersect(region).isEmpty())
1118 reshadowClients.append((*it).client);
1121 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1123 (*it2)->removeShadow();
1124 (*it2)->drawDelayedShadow();
1133 void Client::drawOverlappingShadows(
bool waitForMe)
1137 TQValueList<Client *> reshadowClients;
1138 ClientList stacking_order;
1139 ClientList::ConstIterator it;
1140 TQValueListIterator<ShadowRegion> it2;
1141 TQValueListIterator<Client *> it3;
1143 if (!options->shadowEnabled(
false))
1148 region = shapeBoundingRegion;
1150 stacking_order = workspace()->stackingOrder();
1151 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1157 while (it != stacking_order.end()) {
1158 if ((*it)->windowType() == NET::Dock) {
1169 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1170 if ((*it2).client == (*it)) {
1171 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1172 && !(*it2).region.intersect(region).isEmpty())
1173 reshadowClients.append((*it2).client);
1180 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1181 (*it3)->removeShadow();
1182 if (it3 == reshadowClients.begin()) {
1184 (*it3)->drawShadowAfter(
this);
1186 (*it3)->drawDelayedShadow();
1192 (*it3)->drawShadowAfter(aClient);
1201 void Client::drawDelayedShadow()
1203 shadowDelayTimer->stop();
1204 shadowDelayTimer->start(SHADOW_DELAY,
true);
1210 void Client::drawShadowAfter(Client *after)
1212 shadowAfterClient = after;
1213 connect(after, TQ_SIGNAL(shadowDrawn()), TQ_SLOT(drawShadow()));
1219 void Client::drawShadow()
1223 int i, count, ordering;
1226 if (shadowAfterClient != NULL) {
1227 disconnect(shadowAfterClient, TQ_SIGNAL(shadowDrawn()),
this, TQ_SLOT(drawShadow()));
1228 shadowAfterClient = NULL;
1231 if (!isOnCurrentDesktop())
1238 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1242 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1244 shapeBoundingRegion = TQRegion();
1245 for (i = 0; i < count; i++) {
1247 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1249 shapeBoundingRegion += shapeRectangle;
1255 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1256 shapeBoundingRegion.translate(x(), y());
1259 if (!isShadowed() || hidden || isMinimized() ||
1260 maximizeMode() == MaximizeFull ||
1261 !options->shadowWindowType(windowType())) {
1273 TQMemArray<TQRgb> pixelData;
1274 TQPixmap shadowPixmap;
1276 TQRegion exposedRegion;
1277 ShadowRegion shadowRegion;
1278 int thickness, xOffset, yOffset;
1280 thickness = options->shadowThickness(isActive());
1281 xOffset = options->shadowXOffset(isActive());
1282 yOffset = options->shadowYOffset(isActive());
1283 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1285 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1286 width() + thickness * 2, height() + thickness * 2);
1287 shadowPixmap.resize(shadow.size());
1290 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1291 shadowWidget->setGeometry(shadow);
1292 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1293 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1294 shadowWidget->installEventFilter(
this);
1298 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1299 shadow.y(), shadow.width(), shadow.height(), thickness,
1301 shadowRegion.region = exposedRegion;
1302 shadowRegion.client =
this;
1303 shadowRegions.append(shadowRegion);
1305 if (opacityCache->isNull())
1306 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1307 exposedRegion, thickness,
1308 options->shadowOpacity(isActive()));
1310 imposeCachedShadow(shadowPixmap, exposedRegion);
1313 TQMemArray<TQRect> exposedRects;
1314 TQMemArray<TQRect>::Iterator it, itEnd;
1315 XRectangle *shadowShapes;
1317 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1318 shadow.y(), shadow.width(), shadow.height(), thickness,
1320 shadowRegion.region = exposedRegion;
1321 shadowRegion.client =
this;
1322 shadowRegions.append(shadowRegion);
1325 exposedRects = exposedRegion.rects();
1327 itEnd = exposedRects.end();
1328 shadowShapes =
new XRectangle[exposedRects.count()];
1329 for (it = exposedRects.begin(); it != itEnd; ++it) {
1330 shadowShapes[i].x = (*it).x();
1331 shadowShapes[i].y = (*it).y();
1332 shadowShapes[i].width = (*it).width();
1333 shadowShapes[i].height = (*it).height();
1336 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1337 ShapeBounding, -x() + thickness - xOffset,
1338 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1340 delete [] shadowShapes;
1342 if (opacityCache->isNull())
1343 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1344 exposedRegion, thickness,
1345 options->shadowOpacity(isActive()));
1347 imposeCachedShadow(shadowPixmap, exposedRegion);
1354 shadowWidget->setErasePixmap(shadowPixmap);
1359 ClientList stacking_order = workspace()->stackingOrder();
1360 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1361 if ((*it)->isDesktop())
1364 shadows[0] = (*it)->frameId();
1365 shadows[1] = shadowWidget->winId();
1369 shadows[0] = frameId();
1370 if (shadowWidget != NULL)
1371 shadows[1] = shadowWidget->winId();
1374 XRestackWindows(tqt_xdisplay(), shadows, 2);
1378 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1387 void Client::removeShadow()
1389 TQValueList<ShadowRegion>::Iterator it;
1391 shadowDelayTimer->stop();
1393 if (shadowWidget != NULL) {
1394 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1395 if ((*it).client ==
this) {
1396 shadowRegions.remove(it);
1399 delete shadowWidget;
1400 shadowWidget = NULL;
1408 TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1409 int h,
int thickness,
int xOffset,
int yOffset)
1411 TQRegion exposedRegion;
1413 exposedRegion = TQRegion(x, y, w, h);
1414 exposedRegion -= occludedRegion;
1416 if (thickness > 0) {
1419 TQMemArray<TQRect> occludedRects;
1420 TQMemArray<TQRect>::Iterator it, itEnd;
1421 TQRegion shadowRegion;
1423 occludedRects = occludedRegion.rects();
1424 itEnd = occludedRects.end();
1425 for (it = occludedRects.begin(); it != itEnd; ++it) {
1429 it->setTop(it->top() - thickness + yOffset);
1430 it->setLeft(it->left() - thickness + xOffset);
1431 it->setRight(it->right() + thickness + xOffset);
1432 it->setBottom(it->bottom() + thickness + yOffset);
1433 shadowRegion += TQRegion(*it);
1435 exposedRegion -= exposedRegion - shadowRegion;
1438 return exposedRegion;
1444 void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1448 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1449 int subW, subH, w, x, y, zeroX, zeroY;
1451 TQMemArray<TQRect>::Iterator it, itEnd;
1452 TQMemArray<TQRect> rectangles;
1455 int thickness, windowX, windowY, xOffset, yOffset;
1457 rectangles = exposed.rects();
1458 rootWindow = tqt_xrootwin();
1459 thickness = options->shadowThickness(isActive());
1460 windowX = this->x();
1461 windowY = this->y();
1462 xOffset = options->shadowXOffset(isActive());
1463 yOffset = options->shadowYOffset(isActive());
1464 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1467 itEnd = rectangles.end();
1468 for (it = rectangles.begin(); it != itEnd; ++it) {
1469 subW = (*it).width();
1470 subH = (*it).height();
1471 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1473 zeroX = (*it).x() - windowX + thickness - xOffset;
1474 zeroY = (*it).y() - windowY + thickness - yOffset;
1475 image = subPixmap.convertToImage();
1477 for (x = 0; x < subW; x++) {
1478 for (y = 0; y < subH; y++) {
1479 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1480 pixel = image.pixel(x, y);
1481 pixelRed = tqRed(pixel);
1482 pixelGreen = tqGreen(pixel);
1483 pixelBlue = tqBlue(pixel);
1484 image.setPixel(x, y,
1485 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1486 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1487 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1491 subPixmap.convertFromImage(image);
1492 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1499 void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1500 TQRegion exposed,
int thickness,
double maxOpacity)
1502 int distance, intersectCount, i, j, x, y;
1504 double decay, factor, opacity;
1505 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1506 int lineIntersects, maxIntersects, maxY;
1507 int irBottom, irLeft, irRight, irTop, yIncrement;
1508 int subW, subH, w, h, zeroX, zeroY;
1510 TQMemArray<TQRect>::Iterator it, itEnd;
1511 TQMemArray<TQRect> rectangles;
1514 int windowX, windowY, xOffset, yOffset;
1516 rectangles = exposed.rects();
1517 rootWindow = tqt_xrootwin();
1518 windowX = this->x();
1519 windowY = this->y();
1520 xOffset = options->shadowXOffset(isActive());
1521 yOffset = options->shadowYOffset(isActive());
1522 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1523 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1524 lineIntersects = thickness * 2 + 1;
1525 factor = maxIntersects / maxOpacity;
1526 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1528 h = pixmap.height();
1529 xOffset = options->shadowXOffset(isActive());
1530 yOffset = options->shadowYOffset(isActive());
1532 opacityCache->resize(0);
1533 opacityCache->resize(w * h);
1534 occluded.translate(-windowX + thickness, -windowY + thickness);
1536 itEnd = rectangles.end();
1537 for (it = rectangles.begin(); it != itEnd; ++it) {
1538 subW = (*it).width();
1539 subH = (*it).height();
1540 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1543 zeroX = (*it).x() - windowX + thickness - xOffset;
1544 zeroY = (*it).y() - windowY + thickness - yOffset;
1545 image = subPixmap.convertToImage();
1551 for (x = 0; x < subW; x++) {
1552 irLeft = zeroX + x - thickness;
1553 irRight = zeroX + x + thickness;
1558 irTop = zeroY + y - thickness * yIncrement;
1561 irBottom = zeroY + y + thickness * yIncrement;
1563 if (opacity == -1) {
1568 for (j = irTop; j != irBottom; j += yIncrement) {
1571 for (i = irLeft; i <= irRight; i++) {
1572 if (occluded.contains(TQPoint(i, j)))
1578 if (intersectCount < 0)
1581 for (i = irLeft; i <= irRight; i++) {
1582 if (occluded.contains(TQPoint(i, irBottom)))
1587 distance = maxIntersects - intersectCount;
1588 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1590 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1591 pixel = image.pixel(x, y);
1592 pixelRed = tqRed(pixel);
1593 pixelGreen = tqGreen(pixel);
1594 pixelBlue = tqBlue(pixel);
1595 image.setPixel(x, y,
1596 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1597 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1598 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1600 for (i = irLeft; i <= irRight; i++) {
1601 if (occluded.contains(TQPoint(i, irTop)))
1609 irTop += yIncrement;
1610 for (j = irTop; j != irBottom; j += yIncrement) {
1611 if (occluded.contains(TQPoint(irLeft, j)))
1615 for (j = irTop; j != irBottom; j += yIncrement) {
1616 if (occluded.contains(TQPoint(irRight, j)))
1629 subPixmap.convertFromImage(image);
1630 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1638 void Client::setMappingState(
int s)
1640 assert( client != None );
1641 assert( !deleting || s == WithdrawnState );
1642 if( mapping_state == s )
1644 bool was_unmanaged = ( mapping_state == WithdrawnState );
1646 if( mapping_state == WithdrawnState )
1648 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1651 assert( s == NormalState || s == IconicState );
1653 unsigned long data[2];
1654 data[0] = (
unsigned long) s;
1655 data[1] = (
unsigned long) None;
1656 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1657 PropModeReplace, (
unsigned char *)data, 2);
1660 postponeGeometryUpdates(
false );
1667 void Client::rawShow()
1669 if( decoration != NULL )
1670 decoration->widget()->show();
1671 XMapWindow( tqt_xdisplay(), frame );
1674 XMapWindow( tqt_xdisplay(), wrapper );
1675 XMapWindow( tqt_xdisplay(), client );
1677 if (options->shadowEnabled(isActive()))
1678 drawDelayedShadow();
1686 void Client::rawHide()
1695 drawIntersectingShadows();
1696 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1697 XUnmapWindow( tqt_xdisplay(), frame );
1698 XUnmapWindow( tqt_xdisplay(), wrapper );
1699 XUnmapWindow( tqt_xdisplay(), client );
1700 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1701 if( decoration != NULL )
1702 decoration->widget()->hide();
1703 workspace()->clientHidden(
this );
1706 void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1711 memset(&ev, 0,
sizeof(ev));
1712 ev.xclient.type = ClientMessage;
1713 ev.xclient.window = w;
1714 ev.xclient.message_type = a;
1715 ev.xclient.format = 32;
1716 ev.xclient.data.l[0] = protocol;
1717 ev.xclient.data.l[1] = get_tqt_x_time();
1718 ev.xclient.data.l[2] = data1;
1719 ev.xclient.data.l[3] = data2;
1720 ev.xclient.data.l[4] = data3;
1722 if (w == tqt_xrootwin())
1723 mask = SubstructureRedirectMask;
1724 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1730 bool Client::isCloseable()
const
1732 if( isModalSystemNotification())
1734 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1747 if ( Pdeletewindow )
1749 Notify::raise( Notify::Close );
1750 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1767 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1770 Notify::raise( Notify::Close );
1773 Notify::raise( Notify::TransDelete );
1774 if( isNormalWindow())
1775 Notify::raise( Notify::Delete );
1776 killProcess(
false );
1778 XKillClient(tqt_xdisplay(), window() );
1785 void Client::pingWindow()
1789 if( options->killPingTimeout == 0 )
1791 if( ping_timer != NULL )
1793 ping_timer =
new TQTimer(
this );
1794 connect( ping_timer, TQ_SIGNAL( timeout()), TQ_SLOT( pingTimeout()));
1795 ping_timer->start( options->killPingTimeout,
true );
1796 ping_timestamp = get_tqt_x_time();
1797 workspace()->sendPingToWindow( window(), ping_timestamp );
1800 void Client::gotPing( Time timestamp )
1803 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1807 if( process_killer != NULL )
1809 process_killer->kill();
1810 delete process_killer;
1811 process_killer = NULL;
1815 void Client::pingTimeout()
1817 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1820 killProcess(
true, ping_timestamp );
1823 void Client::killProcess(
bool ask, Time timestamp )
1825 if( process_killer != NULL )
1827 Q_ASSERT( !ask || timestamp != CurrentTime );
1829 pid_t pid = info->pid();
1830 if( pid <= 0 || machine.isEmpty())
1832 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1835 if( machine !=
"localhost" )
1838 proc <<
"xon" << machine <<
"kill" << pid;
1839 proc.start( TDEProcess::DontCare );
1842 ::kill( pid, SIGTERM );
1846 process_killer =
new TDEProcess(
this );
1847 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1848 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1849 <<
"--windowname" <<
caption().utf8()
1850 <<
"--applicationname" << resourceClass()
1851 <<
"--wid" << TQCString().setNum( window())
1852 <<
"--timestamp" << TQCString().setNum( timestamp );
1853 connect( process_killer, TQ_SIGNAL( processExited( TDEProcess* )),
1854 TQ_SLOT( processKillerExited()));
1855 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1857 delete process_killer;
1858 process_killer = NULL;
1864 bool Client::isSuspendable()
const
1866 bool cansuspend =
true;
1867 if( skipTaskbar() || skipPager() )
1870 pid_t pid = info->pid();
1871 if( pid <= 0 || machine.isEmpty())
1873 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1874 if( machine !=
"localhost" )
1881 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1883 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1885 if (procStatFile.open(IO_ReadOnly))
1887 TQByteArray statRaw = procStatFile.readAll();
1888 procStatFile.close();
1890 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1891 char tbuf[PATH_MAX];
1893 TQString state(TQChar(inf->pr_sname));
1895 readlink(TQString(
"/proc/%1/path/a.out").arg(pid).latin1(),
1896 tbuf,
sizeof(tbuf));
1897 tcomm = basename(tbuf);
1899 TQString statString(statRaw);
1900 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1901 TQString tcomm = statFields[1];
1902 TQString state = statFields[2];
1907 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1909 Client* nextclient = *it;
1910 pid_t nextpid = nextclient->info->pid();
1911 TQCString nextmachine = nextclient->wmClientMachine(
true );
1912 if( nextpid > 0 && (!nextmachine.isEmpty()))
1914 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1916 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1922 TQString execname(tcomm);
1923 execname.truncate(execname.length()-1);
1924 execname = execname.remove(0,1);
1926 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1943 bool Client::isResumeable()
const
1946 pid_t pid = info->pid();
1947 if( pid <= 0 || machine.isEmpty())
1949 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1950 if( machine !=
"localhost" )
1957 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1959 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1961 if (procStatFile.open(IO_ReadOnly))
1963 TQByteArray statRaw = procStatFile.readAll();
1964 procStatFile.close();
1966 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1967 TQString state(TQChar(inf->pr_sname));
1969 TQString statString(statRaw);
1970 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1971 TQString tcomm = statFields[1];
1972 TQString state = statFields[2];
1990 bool Client::queryUserSuspendedResume()
1994 if (process_resumer != NULL)
1999 process_resumer =
new TDEProcess(
this );
2000 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
2001 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
2002 <<
"--windowname" <<
caption().utf8()
2003 <<
"--applicationname" << resourceClass()
2004 <<
"--wid" << TQCString().setNum( window());
2005 connect( process_resumer, TQ_SIGNAL( processExited( TDEProcess* )),
2006 TQ_SLOT( processResumerExited()));
2007 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
2009 delete process_resumer;
2010 process_resumer = NULL;
2021 void Client::suspendWindow()
2024 pid_t pid = info->pid();
2025 if( pid <= 0 || machine.isEmpty())
2027 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
2028 if( machine !=
"localhost" )
2034 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2036 Client* nextclient = *it;
2037 pid_t nextpid = nextclient->info->pid();
2038 TQCString nextmachine = nextclient->wmClientMachine(
true );
2039 if( nextpid > 0 && (!nextmachine.isEmpty()))
2041 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2043 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2044 nextclient->info->setVisibleName(newCaption.utf8());
2045 nextclient->info->setVisibleIconName(newCaption.utf8());
2046 nextclient->minimized_before_suspend = nextclient->isMinimized();
2047 nextclient->minimize(
true);
2051 ::kill( pid, SIGSTOP );
2055 void Client::resumeWindow()
2058 pid_t pid = info->pid();
2059 if( pid <= 0 || machine.isEmpty())
2061 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2062 if( machine !=
"localhost" )
2068 ::kill( pid, SIGCONT );
2069 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2071 Client* nextclient = *it;
2072 pid_t nextpid = nextclient->info->pid();
2073 TQCString nextmachine = nextclient->wmClientMachine(
true );
2074 if( nextpid > 0 && (!nextmachine.isEmpty()))
2076 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2078 if (!nextclient->minimized_before_suspend)
2080 nextclient->unminimize(
true);
2082 nextclient->updateCaption();
2089 void Client::processKillerExited()
2091 kdDebug( 1212 ) <<
"Killer exited" << endl;
2092 delete process_killer;
2093 process_killer = NULL;
2096 void Client::processResumerExited()
2098 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2100 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2103 takeFocus( Allowed );
2105 delete process_resumer;
2106 process_resumer = NULL;
2109 void Client::setSkipTaskbar(
bool b,
bool from_outside )
2111 int was_wants_tab_focus = wantsTabFocus();
2114 b = rules()->checkSkipTaskbar( b );
2115 original_skip_taskbar = b;
2117 if ( b == skipTaskbar() )
2120 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2121 updateWindowRules();
2122 if( was_wants_tab_focus != wantsTabFocus())
2123 workspace()->updateFocusChains(
this,
2124 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2127 void Client::setSkipPager(
bool b )
2129 b = rules()->checkSkipPager( b );
2130 if ( b == skipPager() )
2133 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2134 updateWindowRules();
2137 void Client::setModal(
bool m )
2148 void Client::setDesktop(
int desktop )
2150 if(
desktop != NET::OnAllDesktops )
2151 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(),
desktop ));
2155 int was_desk = desk;
2158 if(( was_desk == NET::OnAllDesktops ) != (
desktop == NET::OnAllDesktops ))
2160 if ( isShown(
true ))
2161 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2162 workspace()->updateOnAllDesktopsOfTransients(
this );
2164 if( decoration != NULL )
2165 decoration->desktopChange();
2166 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2168 updateWindowRules();
2171 void Client::setOnAllDesktops(
bool b )
2173 if(( b && isOnAllDesktops())
2174 || ( !b && !isOnAllDesktops()))
2177 setDesktop( NET::OnAllDesktops );
2179 setDesktop( workspace()->currentDesktop());
2182 bool Client::isOnCurrentDesktop()
const
2184 return isOnDesktop( workspace()->currentDesktop());
2187 int Client::screen()
const
2189 if( !options->xineramaEnabled )
2191 return workspace()->screenNumber( geometry().center());
2194 bool Client::isOnScreen(
int screen )
const
2196 if( !options->xineramaEnabled )
2198 return workspace()->screenGeometry( screen ).intersects( geometry());
2202 void Client::takeActivity(
int flags,
bool handled, allowed_t )
2204 if( !handled || !Ptakeactivity )
2206 if( flags & ActivityFocus )
2207 takeFocus( Allowed );
2208 if( flags & ActivityRaise )
2209 workspace()->raiseClient(
this );
2214 static Time previous_activity_timestamp;
2215 static Client* previous_client;
2216 if( previous_activity_timestamp == get_tqt_x_time() && previous_client !=
this )
2218 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2219 kdDebug( 1212 ) << kdBacktrace() << endl;
2221 previous_activity_timestamp = get_tqt_x_time();
2222 previous_client =
this;
2224 workspace()->sendTakeActivity(
this, get_tqt_x_time(), flags );
2228 void Client::takeFocus( allowed_t )
2231 static Time previous_focus_timestamp;
2232 static Client* previous_client;
2233 if( previous_focus_timestamp == get_tqt_x_time() && previous_client !=
this )
2235 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2236 kdDebug( 1212 ) << kdBacktrace() << endl;
2238 previous_focus_timestamp = get_tqt_x_time();
2239 previous_client =
this;
2241 if ( rules()->checkAcceptFocus( input ))
2243 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, get_tqt_x_time() );
2245 bool activePrev = active;
2248 active = activePrev;
2252 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2254 workspace()->setShouldGetFocus(
this );
2266 if (isModalSystemNotification())
2268 return Pcontexthelp;
2282 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2283 TQWhatsThis::enterWhatsThisMode();
2292 void Client::fetchName()
2294 setCaption( readName());
2297 TQString Client::readName()
const
2299 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2300 return TQString::fromUtf8( info->name() );
2302 return KWin::readNameProperty( window(), XA_WM_NAME );
2305 KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2307 void Client::setCaption(
const TQString& s,
bool force )
2309 if ( s != cap_normal || force )
2311 bool reset_name = force;
2312 for(
unsigned int i = 0;
2315 if( !s[ i ].isPrint())
2318 bool was_suffix = ( !cap_suffix.isEmpty());
2319 TQString machine_suffix;
2322 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2323 cap_suffix = machine_suffix + shortcut_suffix;
2324 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2329 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2331 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2332 info->setVisibleName(
caption().utf8() );
2335 if(( (was_suffix && cap_suffix.isEmpty())
2338 info->setVisibleName(
"" );
2339 info->setVisibleIconName(
"" );
2341 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2342 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2344 if( isManaged() && decoration != NULL )
2345 decoration->captionChange();
2349 void Client::updateCaption()
2351 setCaption( cap_normal,
true );
2354 void Client::fetchIconicName()
2357 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2358 s = TQString::fromUtf8( info->iconName() );
2360 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2361 if ( s != cap_iconic )
2363 bool was_set = !cap_iconic.isEmpty();
2365 if( !cap_suffix.isEmpty())
2367 if( !cap_iconic.isEmpty())
2368 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2370 info->setVisibleIconName(
"" );
2379 return full ? cap_normal + cap_suffix : cap_normal;
2382 void Client::getWMHints()
2384 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2386 window_group = None;
2390 if( hints->flags & InputHint )
2391 input = hints->input;
2392 if( hints->flags & WindowGroupHint )
2393 window_group = hints->window_group;
2394 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2395 XFree( (
char*)hints );
2399 updateAllowedActions();
2402 void Client::getMotifHints()
2404 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2405 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2406 motif_noborder = mnoborder;
2407 if( !hasNETSupport())
2409 motif_may_resize = mresize;
2410 motif_may_move = mmove;
2413 motif_may_resize = motif_may_move =
true;
2416 motif_may_close = mclose;
2418 updateDecoration(
true );
2421 void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2425 *icon = KWin::icon( win, 32, 32, TRUE, KWin::NETWM | KWin::WMHints );
2426 if( miniicon != NULL )
2428 if( icon == NULL || !icon->isNull())
2429 *miniicon = KWin::icon( win, 16, 16, TRUE, KWin::NETWM | KWin::WMHints );
2431 *miniicon = TQPixmap();
2435 void Client::getIcons()
2438 readIcons( window(), &icon_pix, &miniicon_pix );
2439 if( icon_pix.isNull())
2441 icon_pix = group()->icon();
2442 miniicon_pix = group()->miniIcon();
2444 if( icon_pix.isNull() && isTransient())
2446 ClientList mainclients = mainClients();
2447 for( ClientList::ConstIterator it = mainclients.begin();
2448 it != mainclients.end() && icon_pix.isNull();
2451 icon_pix = (*it)->icon();
2452 miniicon_pix = (*it)->miniIcon();
2455 if( icon_pix.isNull())
2457 icon_pix = KWin::icon( window(), 32, 32, TRUE, KWin::ClassHint | KWin::XApp );
2458 miniicon_pix = KWin::icon( window(), 16, 16, TRUE, KWin::ClassHint | KWin::XApp );
2460 if( isManaged() && decoration != NULL )
2461 decoration->iconChange();
2464 void Client::getWindowProtocols()
2475 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2477 for (i = 0; i < n; i++)
2478 if (p[i] == atoms->wm_delete_window)
2480 else if (p[i] == atoms->wm_take_focus)
2482 else if (p[i] == atoms->net_wm_take_activity)
2484 else if (p[i] == atoms->net_wm_context_help)
2486 else if (p[i] == atoms->net_wm_ping)
2493 static int nullErrorHandler(Display *, XErrorEvent *)
2503 return getStringProperty(w, tqt_window_role).lower();
2511 return getStringProperty(w, tqt_sm_client_id);
2519 return getStringProperty(w, XA_WM_COMMAND,
' ');
2529 unsigned long nitems = 0;
2530 unsigned long extra = 0;
2531 unsigned char *data = 0;
2533 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2534 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2535 FALSE, XA_WINDOW, &type, &format,
2536 &nitems, &extra, &data );
2537 XSetErrorHandler(oldHandler);
2538 if (status == Success )
2540 if (data && nitems > 0)
2541 result = *((Window*) data);
2548 void Client::getWmClientLeader()
2560 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2572 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2577 void Client::getWmClientMachine()
2579 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2580 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2581 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2582 if( client_machine.isEmpty())
2583 client_machine =
"localhost";
2592 TQCString result = client_machine;
2595 if( result !=
"localhost" && isLocalMachine( result ))
2596 result =
"localhost";
2607 if (wmClientLeaderWin)
2608 return wmClientLeaderWin;
2612 bool Client::wantsTabFocus()
const
2614 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2618 bool Client::wantsInput()
const
2620 return rules()->checkAcceptFocus( input || Ptakefocus );
2623 bool Client::isDesktop()
const
2625 return windowType() == NET::Desktop;
2628 bool Client::isDock()
const
2630 return windowType() == NET::Dock;
2633 bool Client::isTopMenu()
const
2635 return windowType() == NET::TopMenu;
2639 bool Client::isMenu()
const
2641 return windowType() == NET::Menu && !isTopMenu();
2644 bool Client::isToolbar()
const
2646 return windowType() == NET::Toolbar;
2649 bool Client::isSplash()
const
2651 return windowType() == NET::Splash;
2654 bool Client::isUtility()
const
2656 return windowType() == NET::Utility;
2659 bool Client::isDialog()
const
2661 return windowType() == NET::Dialog;
2664 bool Client::isNormalWindow()
const
2666 return windowType() == NET::Normal;
2669 bool Client::isSpecialWindow()
const
2671 return isDesktop() || isDock() || isSplash() || isTopMenu()
2675 NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2677 NET::WindowType wt = info->windowType( supported_types );
2680 NET::WindowType wt2 = rules()->checkType( wt );
2684 info->setWindowType( wt );
2687 if( wt == NET::Menu )
2692 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2693 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2697 const char*
const oo_prefix =
"openoffice.org";
2699 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2701 if( wt == NET::Unknown )
2702 wt = isTransient() ? NET::Dialog : NET::Normal;
2710 void Client::setCursor( Position m )
2718 case PositionTopLeft:
2719 case PositionBottomRight:
2720 setCursor( TQt::sizeFDiagCursor );
2722 case PositionBottomLeft:
2723 case PositionTopRight:
2724 setCursor( TQt::sizeBDiagCursor );
2727 case PositionBottom:
2728 setCursor( TQt::sizeVerCursor );
2732 setCursor( TQt::sizeHorCursor );
2736 setCursor( TQt::sizeAllCursor );
2738 setCursor( TQt::arrowCursor );
2745 void Client::setCursor(
const TQCursor& c )
2747 if( c.handle() == cursor.handle())
2750 if( decoration != NULL )
2751 decoration->widget()->setCursor( cursor );
2752 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2755 Client::Position Client::mousePosition(
const TQPoint& p )
const
2757 if( decoration != NULL )
2758 return decoration->mousePosition( p );
2759 return PositionCenter;
2762 void Client::updateAllowedActions(
bool force )
2764 if( !isManaged() && !force )
2766 unsigned long old_allowed_actions = allowed_actions;
2767 allowed_actions = 0;
2769 allowed_actions |= NET::ActionMove;
2771 allowed_actions |= NET::ActionResize;
2773 allowed_actions |= NET::ActionMinimize;
2775 allowed_actions |= NET::ActionShade;
2777 if( isMaximizable())
2778 allowed_actions |= NET::ActionMax;
2779 if( userCanSetFullScreen())
2780 allowed_actions |= NET::ActionFullScreen;
2781 allowed_actions |= NET::ActionChangeDesktop;
2783 allowed_actions |= NET::ActionClose;
2784 if( old_allowed_actions == allowed_actions )
2787 info->setAllowedActions( allowed_actions );
2791 void Client::autoRaise()
2793 workspace()->raiseClient(
this );
2797 void Client::cancelAutoRaise()
2799 delete autoRaiseTimer;
2803 void Client::setOpacity(
bool translucent, uint opacity)
2809 if (!translucent || opacity == 0xFFFFFFFF)
2811 opacity_ = 0xFFFFFFFF;
2812 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2813 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2816 if(opacity == opacity_)
2819 long data = opacity;
2820 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2821 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2825 void Client::setShadowSize(uint shadowSize)
2829 long data = shadowSize;
2830 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2833 void Client::updateOpacity()
2836 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2840 if( ruleOpacityActive() )
2841 setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2843 setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2847 ClientList tmpGroupMembers = group()->members();
2848 ClientList activeGroupMembers;
2849 activeGroupMembers.append(
this);
2850 tmpGroupMembers.remove(
this);
2851 ClientList::Iterator it = tmpGroupMembers.begin();
2852 while (it != tmpGroupMembers.end())
2855 if ((*it) !=
this && (*it)->isBMP())
2859 if ((*it)->touches(
this))
2862 if( ruleOpacityActive() )
2863 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2865 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2867 (*it)->setShadowSize(options->activeWindowShadowSize);
2868 activeGroupMembers.append(*it);
2869 tmpGroupMembers.remove(it);
2870 it = tmpGroupMembers.begin();
2876 for( ClientList::ConstIterator it2 = activeGroupMembers.begin(); it2 != activeGroupMembers.end(); it2++ )
2878 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2881 if( ruleOpacityActive() )
2882 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2884 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2885 (*it)->setShadowSize(options->activeWindowShadowSize);
2886 activeGroupMembers.append(*it);
2887 tmpGroupMembers.remove(it);
2888 it = tmpGroupMembers.begin();
2894 if (found)
continue;
2900 else if (isNormalWindow())
2903 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2904 if ((*it)->isDialog() || (*it)->isUtility())
2906 if( (*it)->ruleOpacityActive() )
2907 (*it)->setOpacity((*it)->ruleOpacityActive() < 0xFFFFFFFF, (*it)->ruleOpacityActive());
2909 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2915 if( ruleOpacityInactive() )
2916 setOpacity(rule_opacity_inactive < 0xFFFFFFFF, rule_opacity_inactive);
2918 setOpacity(options->translucentInactiveWindows && !(
keepAbove() && options->keepAboveAsActive),
2919 options->inactiveWindowOpacity);
2924 ClientList tmpGroupMembers = group()->members();
2925 ClientList inactiveGroupMembers;
2926 inactiveGroupMembers.append(
this);
2927 tmpGroupMembers.remove(
this);
2928 ClientList::Iterator it = tmpGroupMembers.begin();
2929 while ( it != tmpGroupMembers.end() )
2932 if ((*it) !=
this && (*it)->isBMP())
2936 if ((*it)->touches(
this))
2939 if( (*it)->ruleOpacityInactive() )
2940 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2942 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2943 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2945 inactiveGroupMembers.append(*it);
2946 tmpGroupMembers.remove(it);
2947 it = tmpGroupMembers.begin();
2953 for( ClientList::ConstIterator it2 = inactiveGroupMembers.begin(); it2 != inactiveGroupMembers.end(); it2++ )
2955 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2958 if( (*it)->ruleOpacityInactive() )
2959 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2961 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2962 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2964 inactiveGroupMembers.append(*it);
2965 tmpGroupMembers.remove(it);
2966 it = tmpGroupMembers.begin();
2971 if (found)
continue;
2977 else if (isNormalWindow())
2979 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2980 if ((*it)->isUtility())
2982 if( (*it)->ruleOpacityInactive() )
2983 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2985 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2991 void Client::updateShadowSize()
2994 if (!(isNormalWindow() || isDialog() || isUtility() ))
2997 setShadowSize(options->activeWindowShadowSize);
2999 setShadowSize(options->inactiveWindowShadowSize);
3002 uint Client::ruleOpacityInactive()
3004 return rule_opacity_inactive;
3007 uint Client::ruleOpacityActive()
3009 return rule_opacity_active;
3012 bool Client::getWindowOpacity()
3014 unsigned char *data = 0;
3017 unsigned long n, left;
3018 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
3019 if (result == Success && data && format == 32 )
3021 opacity_ = *
reinterpret_cast< long*
>( data );
3022 custom_opacity =
true;
3024 XFree ((
char*)data);
3030 void Client::setCustomOpacityFlag(
bool custom)
3032 custom_opacity = custom;
3035 uint Client::opacity()
3040 int Client::opacityPercentage()
3042 return int(100*((
double)opacity_/0xffffffff));
3045 bool Client::touches(
const Client* c)
3048 if (y() == c->y() + c->height())
3050 if (y() + height() == c->y())
3052 if (x() == c->x() + c->width())
3054 if (x() + width() == c->x())
3059 void Client::setDecoHashProperty(uint topHeight, uint rightWidth, uint bottomHeight, uint leftWidth)
3061 long data = (topHeight < 255 ? topHeight : 255) << 24 |
3062 (rightWidth < 255 ? rightWidth : 255) << 16 |
3063 (bottomHeight < 255 ? bottomHeight : 255) << 8 |
3064 (leftWidth < 255 ? leftWidth : 255);
3065 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
3068 void Client::unsetDecoHashProperty()
3070 XDeleteProperty( tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash);
3074 kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
3077 return stream <<
"\'NULL_CLIENT\'";
3078 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
3080 kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
3084 for( ClientList::ConstIterator it = list.begin();
3096 kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3100 for( ConstClientList::ConstIterator it = list.begin();
3114 TQPixmap * twin_get_menu_pix_hack()
3118 p = SmallIcon(
"bx2" );
3124 #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)