16 #include <tqapplication.h>
17 #include <tqpainter.h>
18 #include <tqdatetime.h>
23 #include <kstandarddirs.h>
24 #include <tqwhatsthis.h>
26 #include <kiconloader.h>
27 #include <tdelocale.h>
32 #include "workspace.h"
34 #include "notifications.h"
37 #include <X11/extensions/shape.h>
42 extern Atom tqt_wm_state;
43 extern Atom tqt_window_role;
44 extern Atom tqt_sm_client_id;
47 static const int SHADOW_DELAY = 200;
49 namespace KWinInternal
63 static TQValueList<ShadowRegion> shadowRegions;
96 bridge( new Bridge( this )),
97 move_faked_activity( false ),
98 move_resize_grab_window( None ),
99 transient_for( NULL ),
100 transient_for_id( None ),
101 original_transient_for_id( None ),
103 window_group( None ),
104 in_layer( UnknownLayer ),
106 process_killer( NULL ),
107 process_resumer( NULL ),
108 user_time( CurrentTime ),
109 allowed_actions( 0 ),
110 postpone_geometry_updates( 0 ),
111 pending_geometry_update( false ),
112 shade_geometry_change( false ),
118 demandAttentionKNotifyTimer( NULL )
124 shadowDelayTimer =
new TQTimer(
this);
125 opacityCache = &activeOpacityCache;
126 shadowAfterClient = NULL;
129 connect(shadowDelayTimer, TQT_SIGNAL(timeout()), TQT_SLOT(drawShadow()));
132 mapping_state = WithdrawnState;
135 mode = PositionCenter;
137 moveResizeMode = FALSE;
141 shade_mode = ShadeNone;
147 motif_noborder =
false;
148 motif_may_move = TRUE;
149 motif_may_resize = TRUE;
150 motif_may_close = TRUE;
151 fullscreen_mode = FullScreenNone;
152 skip_taskbar = FALSE;
153 original_skip_taskbar =
false;
158 user_noborder =
false;
160 ignore_focus_stealing =
false;
161 demands_attention =
false;
162 check_active_modal =
false;
172 max_mode = MaximizeRestore;
173 maxmode_restore = MaximizeRestore;
177 frame_geometry = TQRect( 0, 0, 100, 100 );
178 client_size = TQSize( 100, 100 );
179 custom_opacity =
false;
180 rule_opacity_active = 0;
181 rule_opacity_inactive = 0;
191 assert(!moveResizeMode);
192 assert( client == None );
193 assert( frame == None && wrapper == None );
194 assert( decoration == NULL );
195 assert( postpone_geometry_updates == 0 );
196 assert( !check_active_modal );
202 void Client::deleteClient( Client* c, allowed_t )
214 workspace()->discardUsedWindowRules(
this,
true );
215 StackingUpdatesBlocker blocker( workspace());
216 if (!custom_opacity) setOpacity(FALSE);
220 drawIntersectingShadows();
222 ++postpone_geometry_updates;
226 setMappingState( WithdrawnState );
230 workspace()->clientHidden(
this );
231 XUnmapWindow( tqt_xdisplay(), frameId());
236 workspace()->removeClient(
this, Allowed );
239 info->setDesktop( 0 );
241 info->setState( 0, info->state());
243 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
244 XDeleteProperty( tqt_xdisplay(), client, atoms->net_frame_extents );
245 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
246 XReparentWindow( tqt_xdisplay(), client, workspace()->rootWin(), x(), y());
247 XRemoveFromSaveSet( tqt_xdisplay(), client );
248 XSelectInput( tqt_xdisplay(), client, NoEventMask );
251 XMapWindow( tqt_xdisplay(), client );
258 XUnmapWindow( tqt_xdisplay(), client );
261 XDestroyWindow( tqt_xdisplay(), wrapper );
263 XDestroyWindow( tqt_xdisplay(), frame );
265 --postpone_geometry_updates;
266 checkNonExistentClients();
267 deleteClient(
this, Allowed );
273 void Client::destroyClient()
277 workspace()->discardUsedWindowRules(
this,
true );
278 StackingUpdatesBlocker blocker( workspace());
282 drawIntersectingShadows();
284 ++postpone_geometry_updates;
287 workspace()->clientHidden(
this );
290 workspace()->removeClient(
this, Allowed );
292 XDestroyWindow( tqt_xdisplay(), wrapper );
294 XDestroyWindow( tqt_xdisplay(), frame );
296 --postpone_geometry_updates;
297 checkNonExistentClients();
298 deleteClient(
this, Allowed );
301 void Client::updateDecoration(
bool check_workspace_pos,
bool force )
303 if( !force && (( decoration == NULL && noBorder())
304 || ( decoration != NULL && !noBorder())))
306 bool do_show =
false;
307 postponeGeometryUpdates(
true );
312 setMask( TQRegion());
313 decoration = workspace()->createDecoration( bridge );
316 decoration->widget()->installEventFilter(
this );
317 XReparentWindow( tqt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
318 decoration->widget()->lower();
319 decoration->borders( border_left, border_right, border_top, border_bottom );
320 options->onlyDecoTranslucent ?
321 setDecoHashProperty(border_top, border_right, border_bottom, border_left):
322 unsetDecoHashProperty();
323 int save_workarea_diff_x = workarea_diff_x;
324 int save_workarea_diff_y = workarea_diff_y;
325 move( calculateGravitation(
false ));
326 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
327 workarea_diff_x = save_workarea_diff_x;
328 workarea_diff_y = save_workarea_diff_y;
333 if( check_workspace_pos )
334 checkWorkspacePosition();
335 postponeGeometryUpdates(
false );
337 decoration->widget()->show();
338 updateFrameExtents();
339 updateOpacityCache();
342 void Client::destroyDecoration()
344 if( decoration != NULL )
348 TQPoint grav = calculateGravitation(
true );
349 border_left = border_right = border_top = border_bottom = 0;
350 setMask( TQRegion());
351 int save_workarea_diff_x = workarea_diff_x;
352 int save_workarea_diff_y = workarea_diff_y;
353 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
355 workarea_diff_x = save_workarea_diff_x;
356 workarea_diff_y = save_workarea_diff_y;
360 void Client::checkBorderSizes()
362 if( decoration == NULL )
364 int new_left, new_right, new_top, new_bottom;
365 decoration->borders( new_left, new_right, new_top, new_bottom );
366 if( new_left == border_left && new_right == border_right
367 && new_top == border_top && new_bottom == border_bottom )
369 GeometryUpdatesPostponer blocker(
this );
370 move( calculateGravitation(
true ));
371 border_left = new_left;
372 border_right = new_right;
373 border_top = new_top;
374 border_bottom = new_bottom;
375 if (border_left != new_left ||
376 border_right != new_right ||
377 border_top != new_top ||
378 border_bottom != new_bottom)
379 options->onlyDecoTranslucent ?
380 setDecoHashProperty(new_top, new_right, new_bottom, new_left):
381 unsetDecoHashProperty();
382 move( calculateGravitation(
false ));
383 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
384 checkWorkspacePosition();
387 void Client::detectNoBorder()
389 if( Shape::hasShape( window()))
394 switch( windowType())
416 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
420 void Client::detectShapable()
422 if( Shape::hasShape( window()))
424 switch( windowType())
444 void Client::updateFrameExtents()
447 strut.left = border_left;
448 strut.right = border_right;
449 strut.top = border_top;
450 strut.bottom = border_bottom;
451 info->setFrameExtents( strut );
459 void Client::resizeDecoration(
const TQSize& s )
461 if( decoration == NULL )
463 TQSize oldsize = decoration->widget()->size();
464 decoration->resize( s );
467 TQResizeEvent e( s, oldsize );
468 TQApplication::sendEvent( decoration->widget(), &e );
470 if (!moveResizeMode && options->shadowEnabled(isActive()))
474 updateOpacityCache();
478 bool Client::noBorder()
const
480 return noborder || isFullScreen() || user_noborder || motif_noborder;
483 bool Client::userCanSetNoBorder()
const
485 return !noborder && !isFullScreen() && !isShade();
488 bool Client::isUserNoBorder()
const
490 return user_noborder;
493 void Client::setUserNoBorder(
bool set )
495 if( !userCanSetNoBorder())
497 set = rules()->checkNoBorder(
set );
498 if( user_noborder ==
set )
501 updateDecoration(
true,
false );
505 bool Client::isModalSystemNotification()
const
507 unsigned char *data = 0;
510 unsigned long n, left;
511 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
512 if (result == Success && data && format == 32 )
519 void Client::updateShape()
522 if( shape() && !noBorder())
525 updateDecoration(
true );
527 updateOpacityCache();
530 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
531 clientPos().x(), clientPos().y(),
532 window(), ShapeBounding, ShapeSet);
538 if( Shape::version() >= 0x11 )
548 static Window helper_window = None;
549 if( helper_window == None )
550 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
551 0, 0, 1, 1, 0, 0, 0 );
552 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
553 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
554 frameId(), ShapeBounding, ShapeSet );
555 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
556 clientPos().x(), clientPos().y(),
557 window(), ShapeBounding, ShapeSubtract );
558 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
559 clientPos().x(), clientPos().y(),
560 window(), ShapeInput, ShapeUnion );
561 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
562 helper_window, ShapeInput, ShapeSet );
566 void Client::setMask(
const TQRegion& reg,
int mode )
570 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
572 else if( mode == X::Unsorted )
573 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
574 reg.handle(), ShapeSet );
577 TQMemArray< TQRect > rects = reg.rects();
578 XRectangle* xrects =
new XRectangle[ rects.count() ];
579 for(
unsigned int i = 0;
583 xrects[ i ].x = rects[ i ].x();
584 xrects[ i ].y = rects[ i ].y();
585 xrects[ i ].width = rects[ i ].width();
586 xrects[ i ].height = rects[ i ].height();
588 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
589 xrects, rects.count(), ShapeSet, mode );
595 TQRegion Client::mask()
const
598 return TQRegion( 0, 0, width(), height());
602 void Client::setShapable(
bool b)
605 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
608 void Client::hideClient(
bool hide )
621 if( isSpecialWindow())
623 if( isModalSystemNotification())
627 bool shown_mainwindow =
false;
628 ClientList mainclients = mainClients();
629 for( ClientList::ConstIterator it = mainclients.begin();
630 it != mainclients.end();
633 if( (*it)->isShown(
true ))
634 shown_mainwindow =
true;
636 if( !shown_mainwindow )
642 if( transientFor() != NULL )
644 if( !wantsTabFocus())
654 if( isModalSystemNotification())
668 info->setState(0, NET::Shaded);
670 Notify::raise( Notify::Minimize );
673 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
674 animateMinimizeOrUnminimize(
true );
679 updateAllowedActions();
680 workspace()->updateMinimizedOfTransients(
this );
682 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
685 void Client::unminimize(
bool avoid_animation )
687 if (!queryUserSuspendedResume())
694 info->setState(NET::Shaded, NET::Shaded);
696 Notify::raise( Notify::UnMinimize );
698 if( isOnCurrentDesktop() && isShown(
true ))
700 if( mainClients().isEmpty() && !avoid_animation )
701 animateMinimizeOrUnminimize( FALSE );
704 updateAllowedActions();
705 workspace()->updateMinimizedOfTransients(
this );
709 extern bool blockAnimation;
711 void Client::animateMinimizeOrUnminimize(
bool minimize )
713 if ( blockAnimation )
715 if ( !options->animateMinimize )
718 if( decoration != NULL && decoration->animateMinimize( minimize ))
725 float lf,rf,tf,bf,step;
727 int speed = options->animateMinimizeSpeed;
733 step = 40. * (11 - speed );
735 NETRect r = info->iconGeometry();
736 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
737 if ( !icongeom.isValid() )
740 TQPixmap pm = animationPixmap( minimize ? width() : icongeom.width() );
742 TQRect before, after;
745 before = TQRect( x(), y(), width(), pm.height() );
746 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
750 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
751 after = TQRect( x(), y(), width(), pm.height() );
754 lf = (after.left() - before.left())/step;
755 rf = (after.right() - before.right())/step;
756 tf = (after.top() - before.top())/step;
757 bf = (after.bottom() - before.bottom())/step;
761 TQRect area = before;
769 TQPainter p ( workspace()->desktopWidget() );
770 bool need_to_clear = FALSE;
776 pm = animationPixmap( area.width() );
777 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
778 p.drawPixmap( area.x(), area.y(), pm );
781 p.drawPixmap( area2.x(), area2.y(), pm3 );
782 need_to_clear = FALSE;
786 XFlush(tqt_xdisplay());
787 XSync( tqt_xdisplay(), FALSE );
791 area.setLeft(before.left() + int(diff*lf));
792 area.setRight(before.right() + int(diff*rf));
793 area.setTop(before.top() + int(diff*tf));
794 area.setBottom(before.bottom() + int(diff*bf));
797 if ( area2.intersects( area ) )
798 p.drawPixmap( area2.x(), area2.y(), pm2 );
802 need_to_clear = TRUE;
805 }
while ( t.elapsed() < step);
806 if (area2 == area || need_to_clear )
807 p.drawPixmap( area2.x(), area2.y(), pm2 );
817 TQPixmap Client::animationPixmap(
int w )
819 TQFont font = options->font(isActive());
820 TQFontMetrics fm( font );
821 TQPixmap pm( w, fm.lineSpacing() );
822 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
824 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
825 p.setFont(options->font(isActive()));
826 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
831 bool Client::isShadeable()
const
833 return !isSpecialWindow() && !noBorder();
836 void Client::setShade( ShadeMode mode )
840 if( isModalSystemNotification())
842 mode = rules()->checkShade( mode );
843 if( shade_mode == mode )
845 bool was_shade = isShade();
846 ShadeMode was_shade_mode = shade_mode;
848 if( was_shade == isShade())
850 if( decoration != NULL )
851 decoration->shadeChange();
855 if( shade_mode == ShadeNormal )
857 if ( isShown(
true ) && isOnCurrentDesktop())
858 Notify::raise( Notify::ShadeUp );
860 else if( shade_mode == ShadeNone )
862 if( isShown(
true ) && isOnCurrentDesktop())
863 Notify::raise( Notify::ShadeDown );
866 assert( decoration != NULL );
867 GeometryUpdatesPostponer blocker(
this );
869 decoration->borders( border_left, border_right, border_top, border_bottom );
871 int as = options->animateShade? 10 : 1;
877 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
880 shade_geometry_change =
true;
881 TQSize s( sizeForClientSize( TQSize( clientSize())));
882 s.setHeight( border_top + border_bottom );
883 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
884 XUnmapWindow( tqt_xdisplay(), wrapper );
885 XUnmapWindow( tqt_xdisplay(), client );
886 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
892 int step = TQMAX( 4, QABS( h - s.height() ) / as )+1;
896 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
897 resizeDecoration( TQSize( s.width(), h ));
898 TQApplication::syncX();
899 }
while ( h > s.height() + step );
903 shade_geometry_change =
false;
906 if( was_shade_mode == ShadeHover )
907 workspace()->activateNextClient(
this );
909 workspace()->focusToNull();
913 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
918 shade_geometry_change =
true;
919 TQSize s( sizeForClientSize( clientSize()));
922 int step = TQMAX( 4, QABS( h - s.height() ) / as )+1;
926 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
927 resizeDecoration( TQSize( s.width(), h ));
931 TQApplication::syncX();
932 }
while ( h < s.height() - step );
935 shade_geometry_change =
false;
937 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
939 XMapWindow( tqt_xdisplay(), wrapperId());
940 XMapWindow( tqt_xdisplay(), window());
941 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
942 if (options->shadowEnabled(
false))
944 for (ClientList::ConstIterator it = transients().begin();
945 it != transients().end(); ++it)
947 (*it)->removeShadow();
948 (*it)->drawDelayedShadow();
953 workspace()->requestFocus(
this );
955 checkMaximizeGeometry();
956 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
957 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
959 updateAllowedActions();
960 workspace()->updateMinimizedOfTransients(
this );
961 decoration->shadeChange();
965 void Client::shadeHover()
967 setShade( ShadeHover );
971 void Client::cancelShadeHover()
973 delete shadeHoverTimer;
977 void Client::toggleShade()
980 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
983 void Client::updateVisibility()
990 setMappingState( IconicState );
991 info->setState( NET::Hidden, NET::Hidden );
992 setSkipTaskbar(
true,
false );
998 setSkipTaskbar( original_skip_taskbar,
false );
1002 setMappingState( IconicState );
1003 info->setState( NET::Hidden, NET::Hidden );
1008 info->setState( 0, NET::Hidden );
1009 if( !isOnCurrentDesktop())
1011 setMappingState( IconicState );
1017 bool belongs_to_desktop =
false;
1018 for( ClientList::ConstIterator it = group()->members().begin();
1019 it != group()->members().end();
1021 if( (*it)->isDesktop())
1023 belongs_to_desktop =
true;
1026 if( !belongs_to_desktop && workspace()->showingDesktop())
1027 workspace()->resetShowingDesktop(
true );
1029 setMappingState( IconicState );
1031 setMappingState( NormalState );
1036 void Client::setShadowed(
bool shadowed)
1040 wasShadowed = isShadowed();
1041 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1051 if (!activeOpacityCache.isNull())
1052 activeOpacityCache.resize(0);
1053 if (!inactiveOpacityCache.isNull())
1054 inactiveOpacityCache.resize(0);
1059 void Client::updateOpacityCache()
1061 if (!activeOpacityCache.isNull())
1062 activeOpacityCache.resize(0);
1063 if (!inactiveOpacityCache.isNull())
1064 inactiveOpacityCache.resize(0);
1066 if (!moveResizeMode) {
1070 drawIntersectingShadows();
1071 if (options->shadowEnabled(isActive()))
1072 drawDelayedShadow();
1080 void Client::drawIntersectingShadows() {
1084 TQValueList<Client *> reshadowClients;
1085 TQValueListIterator<ShadowRegion> it;
1086 TQValueListIterator<Client *> it2;
1088 if (!options->shadowEnabled(
false))
1093 region = shapeBoundingRegion;
1098 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1099 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1100 !(*it).region.intersect(region).isEmpty())
1101 reshadowClients.append((*it).client);
1104 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1106 (*it2)->removeShadow();
1107 (*it2)->drawDelayedShadow();
1116 void Client::drawOverlappingShadows(
bool waitForMe)
1120 TQValueList<Client *> reshadowClients;
1121 ClientList stacking_order;
1122 ClientList::ConstIterator it;
1123 TQValueListIterator<ShadowRegion> it2;
1124 TQValueListIterator<Client *> it3;
1126 if (!options->shadowEnabled(
false))
1131 region = shapeBoundingRegion;
1133 stacking_order = workspace()->stackingOrder();
1134 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1140 while (it != stacking_order.end()) {
1141 if ((*it)->windowType() == NET::Dock) {
1152 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1153 if ((*it2).client == (*it)) {
1154 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1155 && !(*it2).region.intersect(region).isEmpty())
1156 reshadowClients.append((*it2).client);
1163 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1164 (*it3)->removeShadow();
1165 if (it3 == reshadowClients.begin()) {
1167 (*it3)->drawShadowAfter(
this);
1169 (*it3)->drawDelayedShadow();
1175 (*it3)->drawShadowAfter(aClient);
1184 void Client::drawDelayedShadow()
1186 shadowDelayTimer->stop();
1187 shadowDelayTimer->start(SHADOW_DELAY,
true);
1193 void Client::drawShadowAfter(Client *after)
1195 shadowAfterClient = after;
1196 connect(after, TQT_SIGNAL(shadowDrawn()), TQT_SLOT(drawShadow()));
1202 void Client::drawShadow()
1206 int i, count, ordering;
1209 if (shadowAfterClient != NULL) {
1210 disconnect(shadowAfterClient, TQT_SIGNAL(shadowDrawn()),
this, TQT_SLOT(drawShadow()));
1211 shadowAfterClient = NULL;
1214 if (!isOnCurrentDesktop())
1221 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1225 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1227 shapeBoundingRegion = TQRegion();
1228 for (i = 0; i < count; i++) {
1230 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1232 shapeBoundingRegion += shapeRectangle;
1238 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1239 shapeBoundingRegion.translate(x(), y());
1242 if (!isShadowed() || hidden || isMinimized() ||
1243 maximizeMode() == MaximizeFull ||
1244 !options->shadowWindowType(windowType())) {
1256 TQMemArray<QRgb> pixelData;
1257 TQPixmap shadowPixmap;
1259 TQRegion exposedRegion;
1260 ShadowRegion shadowRegion;
1261 int thickness, xOffset, yOffset;
1263 thickness = options->shadowThickness(isActive());
1264 xOffset = options->shadowXOffset(isActive());
1265 yOffset = options->shadowYOffset(isActive());
1266 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1268 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1269 width() + thickness * 2, height() + thickness * 2);
1270 shadowPixmap.resize(shadow.size());
1273 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1274 shadowWidget->setGeometry(shadow);
1275 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1276 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1277 shadowWidget->installEventFilter(
this);
1281 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1282 shadow.y(), shadow.width(), shadow.height(), thickness,
1284 shadowRegion.region = exposedRegion;
1285 shadowRegion.client =
this;
1286 shadowRegions.append(shadowRegion);
1288 if (opacityCache->isNull())
1289 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1290 exposedRegion, thickness,
1291 options->shadowOpacity(isActive()));
1293 imposeCachedShadow(shadowPixmap, exposedRegion);
1296 TQMemArray<TQRect> exposedRects;
1297 TQMemArray<TQRect>::Iterator it, itEnd;
1298 XRectangle *shadowShapes;
1300 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1301 shadow.y(), shadow.width(), shadow.height(), thickness,
1303 shadowRegion.region = exposedRegion;
1304 shadowRegion.client =
this;
1305 shadowRegions.append(shadowRegion);
1308 exposedRects = exposedRegion.rects();
1310 itEnd = exposedRects.end();
1311 shadowShapes =
new XRectangle[exposedRects.count()];
1312 for (it = exposedRects.begin(); it != itEnd; ++it) {
1313 shadowShapes[i].x = (*it).x();
1314 shadowShapes[i].y = (*it).y();
1315 shadowShapes[i].width = (*it).width();
1316 shadowShapes[i].height = (*it).height();
1319 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1320 ShapeBounding, -x() + thickness - xOffset,
1321 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1323 delete [] shadowShapes;
1325 if (opacityCache->isNull())
1326 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1327 exposedRegion, thickness,
1328 options->shadowOpacity(isActive()));
1330 imposeCachedShadow(shadowPixmap, exposedRegion);
1337 shadowWidget->setErasePixmap(shadowPixmap);
1342 ClientList stacking_order = workspace()->stackingOrder();
1343 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1344 if ((*it)->isDesktop())
1347 shadows[0] = (*it)->frameId();
1348 shadows[1] = shadowWidget->winId();
1352 shadows[0] = frameId();
1353 if (shadowWidget != NULL)
1354 shadows[1] = shadowWidget->winId();
1357 XRestackWindows(tqt_xdisplay(), shadows, 2);
1361 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1370 void Client::removeShadow()
1372 TQValueList<ShadowRegion>::Iterator it;
1374 shadowDelayTimer->stop();
1376 if (shadowWidget != NULL) {
1377 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1378 if ((*it).client ==
this) {
1379 shadowRegions.remove(it);
1382 delete shadowWidget;
1383 shadowWidget = NULL;
1391 TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1392 int h,
int thickness,
int xOffset,
int yOffset)
1394 TQRegion exposedRegion;
1396 exposedRegion = TQRegion(x, y, w, h);
1397 exposedRegion -= occludedRegion;
1399 if (thickness > 0) {
1402 TQMemArray<TQRect> occludedRects;
1403 TQMemArray<TQRect>::Iterator it, itEnd;
1404 TQRegion shadowRegion;
1406 occludedRects = occludedRegion.rects();
1407 itEnd = occludedRects.end();
1408 for (it = occludedRects.begin(); it != itEnd; ++it) {
1412 it->setTop(it->top() - thickness + yOffset);
1413 it->setLeft(it->left() - thickness + xOffset);
1414 it->setRight(it->right() + thickness + xOffset);
1415 it->setBottom(it->bottom() + thickness + yOffset);
1416 shadowRegion += TQRegion(*it);
1418 exposedRegion -= exposedRegion - shadowRegion;
1421 return exposedRegion;
1427 void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1431 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1432 int subW, subH, w, x, y, zeroX, zeroY;
1434 TQMemArray<TQRect>::Iterator it, itEnd;
1435 TQMemArray<TQRect> rectangles;
1438 int thickness, windowX, windowY, xOffset, yOffset;
1440 rectangles = exposed.rects();
1441 rootWindow = tqt_xrootwin();
1442 thickness = options->shadowThickness(isActive());
1443 windowX = this->x();
1444 windowY = this->y();
1445 xOffset = options->shadowXOffset(isActive());
1446 yOffset = options->shadowYOffset(isActive());
1447 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1450 itEnd = rectangles.end();
1451 for (it = rectangles.begin(); it != itEnd; ++it) {
1452 subW = (*it).width();
1453 subH = (*it).height();
1454 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1456 zeroX = (*it).x() - windowX + thickness - xOffset;
1457 zeroY = (*it).y() - windowY + thickness - yOffset;
1458 image = subPixmap.convertToImage();
1460 for (x = 0; x < subW; x++) {
1461 for (y = 0; y < subH; y++) {
1462 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1463 pixel = image.pixel(x, y);
1464 pixelRed = tqRed(pixel);
1465 pixelGreen = tqGreen(pixel);
1466 pixelBlue = tqBlue(pixel);
1467 image.setPixel(x, y,
1468 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1469 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1470 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1474 subPixmap.convertFromImage(image);
1475 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1482 void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1483 TQRegion exposed,
int thickness,
double maxOpacity)
1485 int distance, intersectCount, i, j, x, y;
1487 double decay, factor, opacity;
1488 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1489 int lineIntersects, maxIntersects, maxY;
1490 int irBottom, irLeft, irRight, irTop, yIncrement;
1491 int subW, subH, w, h, zeroX, zeroY;
1493 TQMemArray<TQRect>::Iterator it, itEnd;
1494 TQMemArray<TQRect> rectangles;
1497 int windowX, windowY, xOffset, yOffset;
1499 rectangles = exposed.rects();
1500 rootWindow = tqt_xrootwin();
1501 windowX = this->x();
1502 windowY = this->y();
1503 xOffset = options->shadowXOffset(isActive());
1504 yOffset = options->shadowYOffset(isActive());
1505 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1506 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1507 lineIntersects = thickness * 2 + 1;
1508 factor = maxIntersects / maxOpacity;
1509 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1511 h = pixmap.height();
1512 xOffset = options->shadowXOffset(isActive());
1513 yOffset = options->shadowYOffset(isActive());
1515 opacityCache->resize(0);
1516 opacityCache->resize(w * h);
1517 occluded.translate(-windowX + thickness, -windowY + thickness);
1519 itEnd = rectangles.end();
1520 for (it = rectangles.begin(); it != itEnd; ++it) {
1521 subW = (*it).width();
1522 subH = (*it).height();
1523 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1526 zeroX = (*it).x() - windowX + thickness - xOffset;
1527 zeroY = (*it).y() - windowY + thickness - yOffset;
1528 image = subPixmap.convertToImage();
1534 for (x = 0; x < subW; x++) {
1535 irLeft = zeroX + x - thickness;
1536 irRight = zeroX + x + thickness;
1541 irTop = zeroY + y - thickness * yIncrement;
1544 irBottom = zeroY + y + thickness * yIncrement;
1546 if (opacity == -1) {
1551 for (j = irTop; j != irBottom; j += yIncrement) {
1554 for (i = irLeft; i <= irRight; i++) {
1555 if (occluded.contains(TQPoint(i, j)))
1561 if (intersectCount < 0)
1564 for (i = irLeft; i <= irRight; i++) {
1565 if (occluded.contains(TQPoint(i, irBottom)))
1570 distance = maxIntersects - intersectCount;
1571 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1573 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1574 pixel = image.pixel(x, y);
1575 pixelRed = tqRed(pixel);
1576 pixelGreen = tqGreen(pixel);
1577 pixelBlue = tqBlue(pixel);
1578 image.setPixel(x, y,
1579 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1580 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1581 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1583 for (i = irLeft; i <= irRight; i++) {
1584 if (occluded.contains(TQPoint(i, irTop)))
1592 irTop += yIncrement;
1593 for (j = irTop; j != irBottom; j += yIncrement) {
1594 if (occluded.contains(TQPoint(irLeft, j)))
1598 for (j = irTop; j != irBottom; j += yIncrement) {
1599 if (occluded.contains(TQPoint(irRight, j)))
1612 subPixmap.convertFromImage(image);
1613 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1621 void Client::setMappingState(
int s)
1623 assert( client != None );
1624 assert( !deleting || s == WithdrawnState );
1625 if( mapping_state == s )
1627 bool was_unmanaged = ( mapping_state == WithdrawnState );
1629 if( mapping_state == WithdrawnState )
1631 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1634 assert( s == NormalState || s == IconicState );
1636 unsigned long data[2];
1637 data[0] = (
unsigned long) s;
1638 data[1] = (
unsigned long) None;
1639 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1640 PropModeReplace, (
unsigned char *)data, 2);
1643 postponeGeometryUpdates(
false );
1650 void Client::rawShow()
1652 if( decoration != NULL )
1653 decoration->widget()->show();
1654 XMapWindow( tqt_xdisplay(), frame );
1657 XMapWindow( tqt_xdisplay(), wrapper );
1658 XMapWindow( tqt_xdisplay(), client );
1660 if (options->shadowEnabled(isActive()))
1661 drawDelayedShadow();
1669 void Client::rawHide()
1678 drawIntersectingShadows();
1679 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1680 XUnmapWindow( tqt_xdisplay(), frame );
1681 XUnmapWindow( tqt_xdisplay(), wrapper );
1682 XUnmapWindow( tqt_xdisplay(), client );
1683 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1684 if( decoration != NULL )
1685 decoration->widget()->hide();
1686 workspace()->clientHidden(
this );
1689 void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1694 memset(&ev, 0,
sizeof(ev));
1695 ev.xclient.type = ClientMessage;
1696 ev.xclient.window = w;
1697 ev.xclient.message_type = a;
1698 ev.xclient.format = 32;
1699 ev.xclient.data.l[0] = protocol;
1700 ev.xclient.data.l[1] = GET_QT_X_TIME();
1701 ev.xclient.data.l[2] = data1;
1702 ev.xclient.data.l[3] = data2;
1703 ev.xclient.data.l[4] = data3;
1705 if (w == tqt_xrootwin())
1706 mask = SubstructureRedirectMask;
1707 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1713 bool Client::isCloseable()
const
1715 if( isModalSystemNotification())
1717 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1730 if ( Pdeletewindow )
1732 Notify::raise( Notify::Close );
1733 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1750 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1753 Notify::raise( Notify::Close );
1756 Notify::raise( Notify::TransDelete );
1757 if( isNormalWindow())
1758 Notify::raise( Notify::Delete );
1759 killProcess(
false );
1761 XKillClient(tqt_xdisplay(), window() );
1768 void Client::pingWindow()
1772 if( options->killPingTimeout == 0 )
1774 if( ping_timer != NULL )
1776 ping_timer =
new TQTimer(
this );
1777 connect( ping_timer, TQT_SIGNAL( timeout()), TQT_SLOT( pingTimeout()));
1778 ping_timer->start( options->killPingTimeout,
true );
1779 ping_timestamp = GET_QT_X_TIME();
1780 workspace()->sendPingToWindow( window(), ping_timestamp );
1783 void Client::gotPing( Time timestamp )
1786 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1790 if( process_killer != NULL )
1792 process_killer->kill();
1793 delete process_killer;
1794 process_killer = NULL;
1798 void Client::pingTimeout()
1800 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1803 killProcess(
true, ping_timestamp );
1806 void Client::killProcess(
bool ask, Time timestamp )
1808 if( process_killer != NULL )
1810 Q_ASSERT( !ask || timestamp != CurrentTime );
1812 pid_t pid = info->pid();
1813 if( pid <= 0 || machine.isEmpty())
1815 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1818 if( machine !=
"localhost" )
1821 proc <<
"xon" << machine <<
"kill" << pid;
1822 proc.start( TDEProcess::DontCare );
1825 ::kill( pid, SIGTERM );
1829 process_killer =
new TDEProcess(
this );
1830 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1831 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1832 <<
"--windowname" <<
caption().utf8()
1833 <<
"--applicationname" << resourceClass()
1834 <<
"--wid" << TQCString().setNum( window())
1835 <<
"--timestamp" << TQCString().setNum( timestamp );
1836 connect( process_killer, TQT_SIGNAL( processExited( TDEProcess* )),
1837 TQT_SLOT( processKillerExited()));
1838 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1840 delete process_killer;
1841 process_killer = NULL;
1847 bool Client::isSuspendable()
const
1849 bool cansuspend =
true;
1850 if( skipTaskbar() || skipPager() )
1853 pid_t pid = info->pid();
1854 if( pid <= 0 || machine.isEmpty())
1856 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1857 if( machine !=
"localhost" )
1863 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1864 if (procStatFile.open(IO_ReadOnly))
1866 TQByteArray statRaw = procStatFile.readAll();
1867 procStatFile.close();
1868 TQString statString(statRaw);
1869 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1870 TQString tcomm = statFields[1];
1871 TQString state = statFields[2];
1875 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1877 Client* nextclient = *it;
1878 pid_t nextpid = nextclient->info->pid();
1879 TQCString nextmachine = nextclient->wmClientMachine(
true );
1880 if( nextpid > 0 && (!nextmachine.isEmpty()))
1882 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1884 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1890 TQString execname(tcomm);
1891 execname.truncate(execname.length()-1);
1892 execname = execname.remove(0,1);
1894 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1911 bool Client::isResumeable()
const
1914 pid_t pid = info->pid();
1915 if( pid <= 0 || machine.isEmpty())
1917 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1918 if( machine !=
"localhost" )
1924 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1925 if (procStatFile.open(IO_ReadOnly))
1927 TQByteArray statRaw = procStatFile.readAll();
1928 procStatFile.close();
1929 TQString statString(statRaw);
1930 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1931 TQString tcomm = statFields[1];
1932 TQString state = statFields[2];
1949 bool Client::queryUserSuspendedResume()
1953 if (process_resumer != NULL)
1958 process_resumer =
new TDEProcess(
this );
1959 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
1960 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
1961 <<
"--windowname" <<
caption().utf8()
1962 <<
"--applicationname" << resourceClass()
1963 <<
"--wid" << TQCString().setNum( window());
1964 connect( process_resumer, TQT_SIGNAL( processExited( TDEProcess* )),
1965 TQT_SLOT( processResumerExited()));
1966 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
1968 delete process_resumer;
1969 process_resumer = NULL;
1980 void Client::suspendWindow()
1983 pid_t pid = info->pid();
1984 if( pid <= 0 || machine.isEmpty())
1986 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
1987 if( machine !=
"localhost" )
1993 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1995 Client* nextclient = *it;
1996 pid_t nextpid = nextclient->info->pid();
1997 TQCString nextmachine = nextclient->wmClientMachine(
true );
1998 if( nextpid > 0 && (!nextmachine.isEmpty()))
2000 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2002 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2003 nextclient->info->setVisibleName(newCaption.utf8());
2004 nextclient->info->setVisibleIconName(newCaption.utf8());
2005 nextclient->minimized_before_suspend = nextclient->isMinimized();
2006 nextclient->minimize(
true);
2010 ::kill( pid, SIGSTOP );
2014 void Client::resumeWindow()
2017 pid_t pid = info->pid();
2018 if( pid <= 0 || machine.isEmpty())
2020 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2021 if( machine !=
"localhost" )
2027 ::kill( pid, SIGCONT );
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 if (!nextclient->minimized_before_suspend)
2039 nextclient->unminimize(
true);
2041 nextclient->updateCaption();
2048 void Client::processKillerExited()
2050 kdDebug( 1212 ) <<
"Killer exited" << endl;
2051 delete process_killer;
2052 process_killer = NULL;
2055 void Client::processResumerExited()
2057 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2059 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2062 takeFocus( Allowed );
2064 delete process_resumer;
2065 process_resumer = NULL;
2068 void Client::setSkipTaskbar(
bool b,
bool from_outside )
2070 int was_wants_tab_focus = wantsTabFocus();
2073 b = rules()->checkSkipTaskbar( b );
2074 original_skip_taskbar = b;
2076 if ( b == skipTaskbar() )
2079 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2080 updateWindowRules();
2081 if( was_wants_tab_focus != wantsTabFocus())
2082 workspace()->updateFocusChains(
this,
2083 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2086 void Client::setSkipPager(
bool b )
2088 b = rules()->checkSkipPager( b );
2089 if ( b == skipPager() )
2092 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2093 updateWindowRules();
2096 void Client::setModal(
bool m )
2107 void Client::setDesktop(
int desktop )
2109 if( desktop != NET::OnAllDesktops )
2110 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desktop ));
2111 desktop = rules()->checkDesktop( desktop );
2112 if( desk == desktop )
2114 int was_desk = desk;
2116 info->setDesktop( desktop );
2117 if(( was_desk == NET::OnAllDesktops ) != ( desktop == NET::OnAllDesktops ))
2119 if ( isShown(
true ))
2120 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2121 workspace()->updateOnAllDesktopsOfTransients(
this );
2123 if( decoration != NULL )
2124 decoration->desktopChange();
2125 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2127 updateWindowRules();
2130 void Client::setOnAllDesktops(
bool b )
2132 if(( b && isOnAllDesktops())
2133 || ( !b && !isOnAllDesktops()))
2136 setDesktop( NET::OnAllDesktops );
2138 setDesktop( workspace()->currentDesktop());
2141 bool Client::isOnCurrentDesktop()
const
2143 return isOnDesktop( workspace()->currentDesktop());
2146 int Client::screen()
const
2148 if( !options->xineramaEnabled )
2150 return workspace()->screenNumber( geometry().center());
2153 bool Client::isOnScreen(
int screen )
const
2155 if( !options->xineramaEnabled )
2157 return workspace()->screenGeometry( screen ).intersects( geometry());
2161 void Client::takeActivity(
int flags,
bool handled, allowed_t )
2163 if( !handled || !Ptakeactivity )
2165 if( flags & ActivityFocus )
2166 takeFocus( Allowed );
2167 if( flags & ActivityRaise )
2168 workspace()->raiseClient(
this );
2173 static Time previous_activity_timestamp;
2174 static Client* previous_client;
2175 if( previous_activity_timestamp == GET_QT_X_TIME() && previous_client !=
this )
2177 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2178 kdDebug( 1212 ) << kdBacktrace() << endl;
2180 previous_activity_timestamp = GET_QT_X_TIME();
2181 previous_client =
this;
2183 workspace()->sendTakeActivity(
this, GET_QT_X_TIME(), flags );
2187 void Client::takeFocus( allowed_t )
2190 static Time previous_focus_timestamp;
2191 static Client* previous_client;
2192 if( previous_focus_timestamp == GET_QT_X_TIME() && previous_client !=
this )
2194 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2195 kdDebug( 1212 ) << kdBacktrace() << endl;
2197 previous_focus_timestamp = GET_QT_X_TIME();
2198 previous_client =
this;
2200 if ( rules()->checkAcceptFocus( input ))
2202 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, GET_QT_X_TIME() );
2204 bool activePrev = active;
2207 active = activePrev;
2211 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2213 workspace()->setShouldGetFocus(
this );
2225 if (isModalSystemNotification())
2227 return Pcontexthelp;
2241 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2242 TQWhatsThis::enterWhatsThisMode();
2251 void Client::fetchName()
2253 setCaption( readName());
2256 TQString Client::readName()
const
2258 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2259 return TQString::fromUtf8( info->name() );
2261 return KWin::readNameProperty( window(), XA_WM_NAME );
2264 KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2266 void Client::setCaption(
const TQString& s,
bool force )
2268 if ( s != cap_normal || force )
2270 bool reset_name = force;
2271 for(
unsigned int i = 0;
2274 if( !s[ i ].isPrint())
2277 bool was_suffix = ( !cap_suffix.isEmpty());
2278 TQString machine_suffix;
2281 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2282 cap_suffix = machine_suffix + shortcut_suffix;
2283 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2288 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2290 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2291 info->setVisibleName(
caption().utf8() );
2294 if(( (was_suffix && cap_suffix.isEmpty())
2297 info->setVisibleName(
"" );
2298 info->setVisibleIconName(
"" );
2300 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2301 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2303 if( isManaged() && decoration != NULL )
2304 decoration->captionChange();
2308 void Client::updateCaption()
2310 setCaption( cap_normal,
true );
2313 void Client::fetchIconicName()
2316 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2317 s = TQString::fromUtf8( info->iconName() );
2319 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2320 if ( s != cap_iconic )
2322 bool was_set = !cap_iconic.isEmpty();
2324 if( !cap_suffix.isEmpty())
2326 if( !cap_iconic.isEmpty())
2327 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2329 info->setVisibleIconName(
"" );
2338 return full ? cap_normal + cap_suffix : cap_normal;
2341 void Client::getWMHints()
2343 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2345 window_group = None;
2349 if( hints->flags & InputHint )
2350 input = hints->input;
2351 if( hints->flags & WindowGroupHint )
2352 window_group = hints->window_group;
2353 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2354 XFree( (
char*)hints );
2358 updateAllowedActions();
2361 void Client::getMotifHints()
2363 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2364 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2365 motif_noborder = mnoborder;
2366 if( !hasNETSupport())
2368 motif_may_resize = mresize;
2369 motif_may_move = mmove;
2372 motif_may_resize = motif_may_move =
true;
2375 motif_may_close = mclose;
2377 updateDecoration(
true );
2380 void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2384 *icon = KWin::icon( win, 32, 32, TRUE, KWin::NETWM | KWin::WMHints );
2385 if( miniicon != NULL )
2387 if( icon == NULL || !icon->isNull())
2388 *miniicon = KWin::icon( win, 16, 16, TRUE, KWin::NETWM | KWin::WMHints );
2390 *miniicon = TQPixmap();
2394 void Client::getIcons()
2397 readIcons( window(), &icon_pix, &miniicon_pix );
2398 if( icon_pix.isNull())
2400 icon_pix = group()->icon();
2401 miniicon_pix = group()->miniIcon();
2403 if( icon_pix.isNull() && isTransient())
2405 ClientList mainclients = mainClients();
2406 for( ClientList::ConstIterator it = mainclients.begin();
2407 it != mainclients.end() && icon_pix.isNull();
2410 icon_pix = (*it)->icon();
2411 miniicon_pix = (*it)->miniIcon();
2414 if( icon_pix.isNull())
2416 icon_pix = KWin::icon( window(), 32, 32, TRUE, KWin::ClassHint | KWin::XApp );
2417 miniicon_pix = KWin::icon( window(), 16, 16, TRUE, KWin::ClassHint | KWin::XApp );
2419 if( isManaged() && decoration != NULL )
2420 decoration->iconChange();
2423 void Client::getWindowProtocols()
2434 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2436 for (i = 0; i < n; i++)
2437 if (p[i] == atoms->wm_delete_window)
2439 else if (p[i] == atoms->wm_take_focus)
2441 else if (p[i] == atoms->net_wm_take_activity)
2443 else if (p[i] == atoms->net_wm_context_help)
2445 else if (p[i] == atoms->net_wm_ping)
2452 static int nullErrorHandler(Display *, XErrorEvent *)
2462 return getStringProperty(w, tqt_window_role).lower();
2470 return getStringProperty(w, tqt_sm_client_id);
2478 return getStringProperty(w, XA_WM_COMMAND,
' ');
2488 unsigned long nitems = 0;
2489 unsigned long extra = 0;
2490 unsigned char *data = 0;
2492 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2493 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2494 FALSE, XA_WINDOW, &type, &format,
2495 &nitems, &extra, &data );
2496 XSetErrorHandler(oldHandler);
2497 if (status == Success )
2499 if (data && nitems > 0)
2500 result = *((Window*) data);
2507 void Client::getWmClientLeader()
2519 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2531 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2536 void Client::getWmClientMachine()
2538 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2539 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2540 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2541 if( client_machine.isEmpty())
2542 client_machine =
"localhost";
2551 TQCString result = client_machine;
2554 if( result !=
"localhost" && isLocalMachine( result ))
2555 result =
"localhost";
2566 if (wmClientLeaderWin)
2567 return wmClientLeaderWin;
2571 bool Client::wantsTabFocus()
const
2573 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2577 bool Client::wantsInput()
const
2579 return rules()->checkAcceptFocus( input || Ptakefocus );
2582 bool Client::isDesktop()
const
2584 return windowType() == NET::Desktop;
2587 bool Client::isDock()
const
2589 return windowType() == NET::Dock;
2592 bool Client::isTopMenu()
const
2594 return windowType() == NET::TopMenu;
2598 bool Client::isMenu()
const
2600 return windowType() == NET::Menu && !isTopMenu();
2603 bool Client::isToolbar()
const
2605 return windowType() == NET::Toolbar;
2608 bool Client::isSplash()
const
2610 return windowType() == NET::Splash;
2613 bool Client::isUtility()
const
2615 return windowType() == NET::Utility;
2618 bool Client::isDialog()
const
2620 return windowType() == NET::Dialog;
2623 bool Client::isNormalWindow()
const
2625 return windowType() == NET::Normal;
2628 bool Client::isSpecialWindow()
const
2630 return isDesktop() || isDock() || isSplash() || isTopMenu()
2634 NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2636 NET::WindowType wt = info->windowType( supported_types );
2639 NET::WindowType wt2 = rules()->checkType( wt );
2643 info->setWindowType( wt );
2646 if( wt == NET::Menu )
2651 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2652 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2656 const char*
const oo_prefix =
"openoffice.org";
2658 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2660 if( wt == NET::Unknown )
2661 wt = isTransient() ? NET::Dialog : NET::Normal;
2669 void Client::setCursor( Position m )
2677 case PositionTopLeft:
2678 case PositionBottomRight:
2679 setCursor( tqsizeFDiagCursor );
2681 case PositionBottomLeft:
2682 case PositionTopRight:
2683 setCursor( tqsizeBDiagCursor );
2686 case PositionBottom:
2687 setCursor( tqsizeVerCursor );
2691 setCursor( tqsizeHorCursor );
2695 setCursor( tqsizeAllCursor );
2697 setCursor( tqarrowCursor );
2704 void Client::setCursor(
const TQCursor& c )
2706 if( c.handle() == cursor.handle())
2709 if( decoration != NULL )
2710 decoration->widget()->setCursor( cursor );
2711 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2714 Client::Position Client::mousePosition(
const TQPoint& p )
const
2716 if( decoration != NULL )
2717 return decoration->mousePosition( p );
2718 return PositionCenter;
2721 void Client::updateAllowedActions(
bool force )
2723 if( !isManaged() && !force )
2725 unsigned long old_allowed_actions = allowed_actions;
2726 allowed_actions = 0;
2728 allowed_actions |= NET::ActionMove;
2730 allowed_actions |= NET::ActionResize;
2732 allowed_actions |= NET::ActionMinimize;
2734 allowed_actions |= NET::ActionShade;
2736 if( isMaximizable())
2737 allowed_actions |= NET::ActionMax;
2738 if( userCanSetFullScreen())
2739 allowed_actions |= NET::ActionFullScreen;
2740 allowed_actions |= NET::ActionChangeDesktop;
2742 allowed_actions |= NET::ActionClose;
2743 if( old_allowed_actions == allowed_actions )
2746 info->setAllowedActions( allowed_actions );
2750 void Client::autoRaise()
2752 workspace()->raiseClient(
this );
2756 void Client::cancelAutoRaise()
2758 delete autoRaiseTimer;
2762 void Client::setOpacity(
bool translucent, uint opacity)
2768 if (!translucent || opacity == 0xFFFFFFFF)
2770 opacity_ = 0xFFFFFFFF;
2771 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2772 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2775 if(opacity == opacity_)
2778 long data = opacity;
2779 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2780 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2784 void Client::setShadowSize(uint shadowSize)
2788 long data = shadowSize;
2789 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2792 void Client::updateOpacity()
2795 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2799 if( ruleOpacityActive() )
2800 setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2802 setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2806 ClientList tmpGroupMembers = group()->members();
2807 ClientList activeGroupMembers;
2808 activeGroupMembers.append(
this);
2809 tmpGroupMembers.remove(
this);
2810 ClientList::Iterator it = tmpGroupMembers.begin();
2811 while (it != tmpGroupMembers.end())
2814 if ((*it) !=
this && (*it)->isBMP())
2818 if ((*it)->touches(
this))
2821 if( ruleOpacityActive() )
2822 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2824 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2826 (*it)->setShadowSize(options->activeWindowShadowSize);
2827 activeGroupMembers.append(*it);
2828 tmpGroupMembers.remove(it);
2829 it = tmpGroupMembers.begin();
2835 for( ClientList::ConstIterator it2 = activeGroupMembers.begin(); it2 != activeGroupMembers.end(); it2++ )
2837 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2840 if( ruleOpacityActive() )
2841 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2843 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2844 (*it)->setShadowSize(options->activeWindowShadowSize);
2845 activeGroupMembers.append(*it);
2846 tmpGroupMembers.remove(it);
2847 it = tmpGroupMembers.begin();
2853 if (found)
continue;
2859 else if (isNormalWindow())
2862 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2863 if ((*it)->isDialog() || (*it)->isUtility())
2865 if( (*it)->ruleOpacityActive() )
2866 (*it)->setOpacity((*it)->ruleOpacityActive() < 0xFFFFFFFF, (*it)->ruleOpacityActive());
2868 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2874 if( ruleOpacityInactive() )
2875 setOpacity(rule_opacity_inactive < 0xFFFFFFFF, rule_opacity_inactive);
2877 setOpacity(options->translucentInactiveWindows && !(
keepAbove() && options->keepAboveAsActive),
2878 options->inactiveWindowOpacity);
2883 ClientList tmpGroupMembers = group()->members();
2884 ClientList inactiveGroupMembers;
2885 inactiveGroupMembers.append(
this);
2886 tmpGroupMembers.remove(
this);
2887 ClientList::Iterator it = tmpGroupMembers.begin();
2888 while ( it != tmpGroupMembers.end() )
2891 if ((*it) !=
this && (*it)->isBMP())
2895 if ((*it)->touches(
this))
2898 if( (*it)->ruleOpacityInactive() )
2899 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2901 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2902 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2904 inactiveGroupMembers.append(*it);
2905 tmpGroupMembers.remove(it);
2906 it = tmpGroupMembers.begin();
2912 for( ClientList::ConstIterator it2 = inactiveGroupMembers.begin(); it2 != inactiveGroupMembers.end(); it2++ )
2914 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2917 if( (*it)->ruleOpacityInactive() )
2918 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2920 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2921 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2923 inactiveGroupMembers.append(*it);
2924 tmpGroupMembers.remove(it);
2925 it = tmpGroupMembers.begin();
2930 if (found)
continue;
2936 else if (isNormalWindow())
2938 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2939 if ((*it)->isUtility())
2941 if( (*it)->ruleOpacityInactive() )
2942 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2944 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2950 void Client::updateShadowSize()
2953 if (!(isNormalWindow() || isDialog() || isUtility() ))
2956 setShadowSize(options->activeWindowShadowSize);
2958 setShadowSize(options->inactiveWindowShadowSize);
2961 uint Client::ruleOpacityInactive()
2963 return rule_opacity_inactive;
2966 uint Client::ruleOpacityActive()
2968 return rule_opacity_active;
2971 bool Client::getWindowOpacity()
2973 unsigned char *data = 0;
2976 unsigned long n, left;
2977 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
2978 if (result == Success && data && format == 32 )
2980 opacity_ = *
reinterpret_cast< long*
>( data );
2981 custom_opacity =
true;
2983 XFree ((
char*)data);
2989 void Client::setCustomOpacityFlag(
bool custom)
2991 custom_opacity = custom;
2994 uint Client::opacity()
2999 int Client::opacityPercentage()
3001 return int(100*((
double)opacity_/0xffffffff));
3004 bool Client::touches(
const Client* c)
3007 if (y() == c->y() + c->height())
3009 if (y() + height() == c->y())
3011 if (x() == c->x() + c->width())
3013 if (x() + width() == c->x())
3018 void Client::setDecoHashProperty(uint topHeight, uint rightWidth, uint bottomHeight, uint leftWidth)
3020 long data = (topHeight < 255 ? topHeight : 255) << 24 |
3021 (rightWidth < 255 ? rightWidth : 255) << 16 |
3022 (bottomHeight < 255 ? bottomHeight : 255) << 8 |
3023 (leftWidth < 255 ? leftWidth : 255);
3024 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
3027 void Client::unsetDecoHashProperty()
3029 XDeleteProperty( tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash);
3033 kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
3036 return stream <<
"\'NULL_CLIENT\'";
3037 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
3039 kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
3043 for( ClientList::ConstIterator it = list.begin();
3055 kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3059 for( ConstClientList::ConstIterator it = list.begin();
3073 TQPixmap * twin_get_menu_pix_hack()
3077 p = SmallIcon(
"bx2" );
3083 #include "client.moc"