16#include <tqapplication.h>
18#include <tqdatetime.h>
21#include <tdeprocess.h>
23#include <tdestandarddirs.h>
24#include <tqwhatsthis.h>
26#include <kiconloader.h>
39#include "notifications.h"
42#include <X11/extensions/shape.h>
47extern Atom tqt_wm_state;
48extern Atom tqt_window_role;
49extern Atom tqt_sm_client_id;
52static const int SHADOW_DELAY = 200;
68static TQValueList<ShadowRegion> shadowRegions;
101 bridge( new Bridge( this )),
102 move_faked_activity( false ),
103 move_resize_grab_window( None ),
104 transient_for( NULL ),
105 transient_for_id( None ),
106 original_transient_for_id( None ),
108 window_group( None ),
109 in_layer( UnknownLayer ),
111 process_killer( NULL ),
112 process_resumer( NULL ),
113 user_time( CurrentTime ),
114 allowed_actions( 0 ),
115 postpone_geometry_updates( 0 ),
116 pending_geometry_update( false ),
117 shade_geometry_change( false ),
122 opacity_( Opacity::Opaque ),
123 demandAttentionKNotifyTimer( NULL ),
124 activeMaximizing(false),
131 shadowDelayTimer =
new TQTimer(
this);
132 opacityCache = &activeOpacityCache;
133 shadowAfterClient = NULL;
136 connect(shadowDelayTimer, TQ_SIGNAL(timeout()), TQ_SLOT(drawShadow()));
139 mapping_state = WithdrawnState;
142 mode = PositionCenter;
144 moveResizeMode =
false;
148 shade_mode = ShadeNone;
154 motif_noborder =
false;
155 motif_may_move =
true;
156 motif_may_resize =
true;
157 motif_may_close =
true;
158 fullscreen_mode = FullScreenNone;
159 skip_taskbar =
false;
160 original_skip_taskbar =
false;
165 user_noborder =
false;
166 user_noborder_forced =
false;
168 ignore_focus_stealing =
false;
169 demands_attention =
false;
170 check_active_modal =
false;
180 max_mode = MaximizeRestore;
181 maxmode_restore = MaximizeRestore;
185 frame_geometry = TQRect( 0, 0, 100, 100 );
186 client_size = TQSize( 100, 100 );
187 custom_opacity =
false;
188 rule_opacity_active = 0;
189 rule_opacity_inactive = 0;
199 assert(!moveResizeMode);
200 assert( client == None );
201 assert( frame == None && wrapper == None );
202 assert( decoration == NULL );
203 assert( postpone_geometry_updates == 0 );
204 assert( !check_active_modal );
210void Client::deleteClient( Client* c, allowed_t )
222 workspace()->discardUsedWindowRules(
this,
true );
223 StackingUpdatesBlocker blocker( workspace());
224 if (!custom_opacity) setOpacity(Opacity::Opaque);
228 drawIntersectingShadows();
230 ++postpone_geometry_updates;
234 setMappingState( WithdrawnState );
238 workspace()->clientHidden(
this );
239 XUnmapWindow( tqt_xdisplay(), frameId());
244 workspace()->removeClient(
this, Allowed );
247 info->setDesktop( 0 );
249 info->setState( 0, info->state());
251 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
252 XDeleteProperty( tqt_xdisplay(), client, atoms->net_frame_extents );
253 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
254 XReparentWindow( tqt_xdisplay(), client, workspace()->rootWin(), x(), y());
255 XRemoveFromSaveSet( tqt_xdisplay(), client );
256 XSelectInput( tqt_xdisplay(), client, NoEventMask );
259 XMapWindow( tqt_xdisplay(), client );
266 XUnmapWindow( tqt_xdisplay(), client );
269 XDestroyWindow( tqt_xdisplay(), wrapper );
271 XDestroyWindow( tqt_xdisplay(), frame );
273 --postpone_geometry_updates;
274 checkNonExistentClients();
275 deleteClient(
this, Allowed );
281void Client::destroyClient()
285 workspace()->discardUsedWindowRules(
this,
true );
286 StackingUpdatesBlocker blocker( workspace());
290 drawIntersectingShadows();
292 ++postpone_geometry_updates;
295 workspace()->clientHidden(
this );
298 workspace()->removeClient(
this, Allowed );
300 XDestroyWindow( tqt_xdisplay(), wrapper );
302 XDestroyWindow( tqt_xdisplay(), frame );
304 --postpone_geometry_updates;
305 checkNonExistentClients();
306 deleteClient(
this, Allowed );
309void Client::updateDecoration(
bool check_workspace_pos,
bool force )
311 if( !force && (( decoration == NULL && noBorder())
312 || ( decoration != NULL && !noBorder())))
314 bool do_show =
false;
315 postponeGeometryUpdates(
true );
320 setMask( TQRegion());
321 decoration = workspace()->createDecoration( bridge );
324 decoration->widget()->installEventFilter(
this );
325 XReparentWindow( tqt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
326 decoration->widget()->lower();
327 decoration->borders( border_left, border_right, border_top, border_bottom );
328 int save_workarea_diff_x = workarea_diff_x;
329 int save_workarea_diff_y = workarea_diff_y;
330 move( calculateGravitation(
false ));
331 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
332 workarea_diff_x = save_workarea_diff_x;
333 workarea_diff_y = save_workarea_diff_y;
338 if( check_workspace_pos )
339 checkWorkspacePosition();
340 postponeGeometryUpdates(
false );
342 decoration->widget()->show();
343 updateFrameExtents();
344 updateOpacityCache();
347void Client::destroyDecoration()
349 if( decoration != NULL )
353 TQPoint grav = calculateGravitation(
true );
354 border_left = border_right = border_top = border_bottom = 0;
355 setMask( TQRegion());
356 int save_workarea_diff_x = workarea_diff_x;
357 int save_workarea_diff_y = workarea_diff_y;
358 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
360 workarea_diff_x = save_workarea_diff_x;
361 workarea_diff_y = save_workarea_diff_y;
365void Client::checkBorderSizes()
367 if( decoration == NULL )
369 int new_left, new_right, new_top, new_bottom;
370 decoration->borders( new_left, new_right, new_top, new_bottom );
371 if( new_left == border_left && new_right == border_right
372 && new_top == border_top && new_bottom == border_bottom )
374 GeometryUpdatesPostponer blocker(
this );
375 move( calculateGravitation(
true ));
376 border_left = new_left;
377 border_right = new_right;
378 border_top = new_top;
379 border_bottom = new_bottom;
380 if (border_left != new_left ||
381 border_right != new_right ||
382 border_top != new_top ||
383 border_bottom != new_bottom)
384 move( calculateGravitation(
false ));
385 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
386 checkWorkspacePosition();
389void Client::detectNoBorder()
391 if( Shape::hasShape( window()))
396 switch( windowType())
418 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
422void Client::detectShapable()
424 if( Shape::hasShape( window()))
426 switch( windowType())
446void Client::updateFrameExtents()
449 strut.left = border_left;
450 strut.right = border_right;
451 strut.top = border_top;
452 strut.bottom = border_bottom;
453 info->setFrameExtents( strut );
461void Client::resizeDecoration(
const TQSize& s )
463 if( decoration == NULL )
465 TQSize oldsize = decoration->widget()->size();
466 decoration->resize( s );
469 TQResizeEvent e( s, oldsize );
470 TQApplication::sendEvent( decoration->widget(), &e );
472 if (!moveResizeMode && options->shadowEnabled(isActive()))
476 updateOpacityCache();
480bool Client::noBorder()
const
482 return noborder || isFullScreen() || user_noborder || ( !user_noborder_forced && motif_noborder );
485bool Client::userCanSetNoBorder()
const
487 return !noborder && !isFullScreen() && !isShade();
490bool Client::isUserNoBorder()
const
492 return user_noborder;
495void Client::setUserNoBorder(
bool set )
497 setUserNoBorder(set,
true);
500void Client::setUserNoBorder(
bool set,
bool forced )
502 if( !userCanSetNoBorder())
504 auto noBorderApply = rules()->applyNoBorder( set );
505 set = noBorderApply.value;
506 forced |= noBorderApply.wasApplied;
508 if( user_noborder == set && user_noborder_forced == forced )
511 user_noborder_forced = forced;
512 updateDecoration(
true,
false );
516bool Client::isUserNoBorderForced()
const
518 return user_noborder_forced;
521bool Client::isModalSystemNotification()
const
523 unsigned char *data = 0;
526 unsigned long n, left;
527 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
528 if (result == Success && data && format == 32 )
535void Client::updateShape()
538 if( shape() && !noBorder())
541 updateDecoration(
true );
543 updateOpacityCache();
546 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
547 clientPos().x(), clientPos().y(),
548 window(), ShapeBounding, ShapeSet);
554 if( Shape::version() >= 0x11 )
564 static Window helper_window = None;
565 if( helper_window == None )
566 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
567 0, 0, 1, 1, 0, 0, 0 );
568 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
569 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
570 frameId(), ShapeBounding, ShapeSet );
571 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
572 clientPos().x(), clientPos().y(),
573 window(), ShapeBounding, ShapeSubtract );
574 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
575 clientPos().x(), clientPos().y(),
576 window(), ShapeInput, ShapeUnion );
577 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
578 helper_window, ShapeInput, ShapeSet );
582void Client::setMask(
const TQRegion& reg,
int mode )
586 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
588 else if( mode == X::Unsorted )
589 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
590 reg.handle(), ShapeSet );
593 TQMemArray< TQRect > rects = reg.rects();
594 XRectangle* xrects =
new XRectangle[ rects.count() ];
595 for(
unsigned int i = 0;
599 xrects[ i ].x = rects[ i ].x();
600 xrects[ i ].y = rects[ i ].y();
601 xrects[ i ].width = rects[ i ].width();
602 xrects[ i ].height = rects[ i ].height();
604 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
605 xrects, rects.count(), ShapeSet, mode );
611TQRegion Client::mask()
const
614 return TQRegion( 0, 0, width(), height());
618void Client::setShapable(
bool b)
621 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
624void Client::hideClient(
bool hide )
637 if( isSpecialWindow())
639 if( isModalSystemNotification())
643 bool shown_mainwindow =
false;
644 ClientList mainclients = mainClients();
645 for( ClientList::ConstIterator it = mainclients.begin();
646 it != mainclients.end();
649 if( (*it)->isShown(
true ))
650 shown_mainwindow =
true;
652 if( !shown_mainwindow )
658 if( transientFor() != NULL )
660 if( !wantsTabFocus())
670 if( isModalSystemNotification())
684 info->setState(0, NET::Shaded);
686 Notify::raise( Notify::Minimize );
689 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
690 animateMinimizeOrUnminimize(
true );
695 updateAllowedActions();
696 workspace()->updateMinimizedOfTransients(
this );
698 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
701void Client::unminimize(
bool avoid_animation )
703 if (!queryUserSuspendedResume())
710 info->setState(NET::Shaded, NET::Shaded);
712 Notify::raise( Notify::UnMinimize );
714 if( isOnCurrentDesktop() && isShown(
true ))
716 if( mainClients().isEmpty() && !avoid_animation )
717 animateMinimizeOrUnminimize(
false );
720 updateAllowedActions();
721 workspace()->updateMinimizedOfTransients(
this );
725extern bool blockAnimation;
727void Client::animateMinimizeOrUnminimize(
bool minimize )
729 if ( blockAnimation )
731 if ( !options->animateMinimize )
734 if( decoration != NULL && decoration->animateMinimize(
minimize ))
741 float lf,rf,tf,bf,step;
743 int speed = options->animateMinimizeSpeed;
749 step = 40. * (11 - speed );
751 NETRect r = info->iconGeometry();
752 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
753 if ( !icongeom.isValid() )
756 TQPixmap pm = animationPixmap(
minimize ? width() : icongeom.width() );
758 TQRect before, after;
761 before = TQRect( x(), y(), width(), pm.height() );
762 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
766 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
767 after = TQRect( x(), y(), width(), pm.height() );
770 lf = (after.left() - before.left())/step;
771 rf = (after.right() - before.right())/step;
772 tf = (after.top() - before.top())/step;
773 bf = (after.bottom() - before.bottom())/step;
777 TQRect area = before;
785 TQPainter p ( workspace()->desktopWidget() );
786 bool need_to_clear =
false;
792 pm = animationPixmap( area.width() );
793 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
794 p.drawPixmap( area.x(), area.y(), pm );
797 p.drawPixmap( area2.x(), area2.y(), pm3 );
798 need_to_clear =
false;
802 XFlush(tqt_xdisplay());
803 XSync( tqt_xdisplay(), False );
807 area.setLeft(before.left() +
int(diff*lf));
808 area.setRight(before.right() +
int(diff*rf));
809 area.setTop(before.top() +
int(diff*tf));
810 area.setBottom(before.bottom() +
int(diff*bf));
813 if ( area2.intersects( area ) )
814 p.drawPixmap( area2.x(), area2.y(), pm2 );
818 need_to_clear =
true;
821 }
while ( t.elapsed() < step);
822 if (area2 == area || need_to_clear )
823 p.drawPixmap( area2.x(), area2.y(), pm2 );
833TQPixmap Client::animationPixmap(
int w )
835 TQFont font = options->font(isActive());
836 TQFontMetrics fm( font );
837 TQPixmap pm( w, fm.lineSpacing() );
838 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
840 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
841 p.setFont(options->font(isActive()));
842 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
847bool Client::isShadeable()
const
849 return !isSpecialWindow() && !noBorder();
852void Client::setShade( ShadeMode mode )
856 if( isModalSystemNotification())
858 mode = rules()->checkShade( mode );
859 if( shade_mode == mode )
861 bool was_shade = isShade();
862 ShadeMode was_shade_mode = shade_mode;
864 if( was_shade == isShade())
866 if( decoration != NULL )
867 decoration->shadeChange();
871 if( shade_mode == ShadeNormal )
873 if ( isShown(
true ) && isOnCurrentDesktop())
874 Notify::raise( Notify::ShadeUp );
876 else if( shade_mode == ShadeNone )
878 if( isShown(
true ) && isOnCurrentDesktop())
879 Notify::raise( Notify::ShadeDown );
882 assert( decoration != NULL );
883 GeometryUpdatesPostponer blocker(
this );
885 decoration->borders( border_left, border_right, border_top, border_bottom );
887 int as = options->animateShade? 10 : 1;
893 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
896 shade_geometry_change =
true;
897 TQSize s( sizeForClientSize( TQSize( clientSize())));
898 s.setHeight( border_top + border_bottom );
899 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
900 XUnmapWindow( tqt_xdisplay(), wrapper );
901 XUnmapWindow( tqt_xdisplay(), client );
902 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
908 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
912 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
913 resizeDecoration( TQSize( s.width(), h ));
914 TQApplication::syncX();
915 }
while ( h > s.height() + step );
919 shade_geometry_change =
false;
922 if( was_shade_mode == ShadeHover )
923 workspace()->activateNextClient(
this );
925 workspace()->focusToNull();
929 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
934 shade_geometry_change =
true;
935 TQSize s( sizeForClientSize( clientSize()));
938 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
942 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
943 resizeDecoration( TQSize( s.width(), h ));
947 TQApplication::syncX();
948 }
while ( h < s.height() - step );
951 shade_geometry_change =
false;
953 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
955 XMapWindow( tqt_xdisplay(), wrapperId());
956 XMapWindow( tqt_xdisplay(), window());
957 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
958 if (options->shadowEnabled(
false))
960 for (ClientList::ConstIterator it = transients().begin();
961 it != transients().end(); ++it)
963 (*it)->removeShadow();
964 (*it)->drawDelayedShadow();
969 workspace()->requestFocus(
this );
971 checkMaximizeGeometry();
972 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
973 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
975 updateAllowedActions();
976 workspace()->updateMinimizedOfTransients(
this );
977 decoration->shadeChange();
981void Client::shadeHover()
983 setShade( ShadeHover );
987void Client::cancelShadeHover()
989 delete shadeHoverTimer;
993void Client::toggleShade()
996 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
999void Client::updateVisibility()
1006 setMappingState( IconicState );
1007 info->setState( NET::Hidden, NET::Hidden );
1008 setSkipTaskbar(
true,
false );
1014 setSkipTaskbar( original_skip_taskbar,
false );
1018 setMappingState( IconicState );
1019 info->setState( NET::Hidden, NET::Hidden );
1024 info->setState( 0, NET::Hidden );
1025 if( !isOnCurrentDesktop())
1027 setMappingState( IconicState );
1033 bool belongs_to_desktop =
false;
1034 for( ClientList::ConstIterator it = group()->members().begin();
1035 it != group()->members().end();
1037 if( (*it)->isDesktop())
1039 belongs_to_desktop =
true;
1042 if( !belongs_to_desktop && workspace()->showingDesktop())
1043 workspace()->resetShowingDesktop(
true );
1045 setMappingState( IconicState );
1047 setMappingState( NormalState );
1052void Client::setShadowed(
bool shadowed)
1056 wasShadowed = isShadowed();
1057 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1067 if (!activeOpacityCache.isNull())
1068 activeOpacityCache.resize(0);
1069 if (!inactiveOpacityCache.isNull())
1070 inactiveOpacityCache.resize(0);
1075void Client::updateOpacityCache()
1077 if (!activeOpacityCache.isNull())
1078 activeOpacityCache.resize(0);
1079 if (!inactiveOpacityCache.isNull())
1080 inactiveOpacityCache.resize(0);
1082 if (!moveResizeMode) {
1086 drawIntersectingShadows();
1087 if (options->shadowEnabled(isActive()))
1088 drawDelayedShadow();
1096void Client::drawIntersectingShadows() {
1100 TQValueList<Client *> reshadowClients;
1101 TQValueListIterator<ShadowRegion> it;
1102 TQValueListIterator<Client *> it2;
1104 if (!options->shadowEnabled(
false))
1109 region = shapeBoundingRegion;
1114 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1115 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1116 !(*it).region.intersect(region).isEmpty())
1117 reshadowClients.append((*it).client);
1120 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1122 (*it2)->removeShadow();
1123 (*it2)->drawDelayedShadow();
1132void Client::drawOverlappingShadows(
bool waitForMe)
1136 TQValueList<Client *> reshadowClients;
1137 ClientList stacking_order;
1138 ClientList::ConstIterator it;
1139 TQValueListIterator<ShadowRegion> it2;
1140 TQValueListIterator<Client *> it3;
1142 if (!options->shadowEnabled(
false))
1147 region = shapeBoundingRegion;
1149 stacking_order = workspace()->stackingOrder();
1150 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1156 while (it != stacking_order.end()) {
1157 if ((*it)->windowType() == NET::Dock) {
1168 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1169 if ((*it2).client == (*it)) {
1170 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1171 && !(*it2).region.intersect(region).isEmpty())
1172 reshadowClients.append((*it2).client);
1179 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1180 (*it3)->removeShadow();
1181 if (it3 == reshadowClients.begin()) {
1183 (*it3)->drawShadowAfter(
this);
1185 (*it3)->drawDelayedShadow();
1191 (*it3)->drawShadowAfter(aClient);
1200void Client::drawDelayedShadow()
1202 shadowDelayTimer->stop();
1203 shadowDelayTimer->start(SHADOW_DELAY,
true);
1209void Client::drawShadowAfter(Client *after)
1211 shadowAfterClient = after;
1212 connect(after, TQ_SIGNAL(shadowDrawn()), TQ_SLOT(drawShadow()));
1218void Client::drawShadow()
1222 int i, count, ordering;
1225 if (shadowAfterClient != NULL) {
1226 disconnect(shadowAfterClient, TQ_SIGNAL(shadowDrawn()),
this, TQ_SLOT(drawShadow()));
1227 shadowAfterClient = NULL;
1230 if (!isOnCurrentDesktop())
1237 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1241 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1243 shapeBoundingRegion = TQRegion();
1244 for (i = 0; i < count; i++) {
1246 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1248 shapeBoundingRegion += shapeRectangle;
1254 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1255 shapeBoundingRegion.translate(x(), y());
1258 if (!isShadowed() || hidden || isMinimized() ||
1259 maximizeMode() == MaximizeFull ||
1260 !options->shadowWindowType(windowType())) {
1272 TQMemArray<TQRgb> pixelData;
1273 TQPixmap shadowPixmap;
1275 TQRegion exposedRegion;
1276 ShadowRegion shadowRegion;
1277 int thickness, xOffset, yOffset;
1279 thickness = options->shadowThickness(isActive());
1280 xOffset = options->shadowXOffset(isActive());
1281 yOffset = options->shadowYOffset(isActive());
1282 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1284 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1285 width() + thickness * 2, height() + thickness * 2);
1286 shadowPixmap.resize(shadow.size());
1289 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1290 shadowWidget->setGeometry(shadow);
1291 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1292 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1293 shadowWidget->installEventFilter(
this);
1297 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1298 shadow.y(), shadow.width(), shadow.height(), thickness,
1300 shadowRegion.region = exposedRegion;
1301 shadowRegion.client =
this;
1302 shadowRegions.append(shadowRegion);
1304 if (opacityCache->isNull())
1305 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1306 exposedRegion, thickness,
1307 options->shadowOpacity(isActive()));
1309 imposeCachedShadow(shadowPixmap, exposedRegion);
1312 TQMemArray<TQRect> exposedRects;
1313 TQMemArray<TQRect>::Iterator it, itEnd;
1314 XRectangle *shadowShapes;
1316 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1317 shadow.y(), shadow.width(), shadow.height(), thickness,
1319 shadowRegion.region = exposedRegion;
1320 shadowRegion.client =
this;
1321 shadowRegions.append(shadowRegion);
1324 exposedRects = exposedRegion.rects();
1326 itEnd = exposedRects.end();
1327 shadowShapes =
new XRectangle[exposedRects.count()];
1328 for (it = exposedRects.begin(); it != itEnd; ++it) {
1329 shadowShapes[i].x = (*it).x();
1330 shadowShapes[i].y = (*it).y();
1331 shadowShapes[i].width = (*it).width();
1332 shadowShapes[i].height = (*it).height();
1335 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1336 ShapeBounding, -x() + thickness - xOffset,
1337 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1339 delete [] shadowShapes;
1341 if (opacityCache->isNull())
1342 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1343 exposedRegion, thickness,
1344 options->shadowOpacity(isActive()));
1346 imposeCachedShadow(shadowPixmap, exposedRegion);
1353 shadowWidget->setErasePixmap(shadowPixmap);
1358 ClientList stacking_order = workspace()->stackingOrder();
1359 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1360 if ((*it)->isDesktop())
1363 shadows[0] = (*it)->frameId();
1364 shadows[1] = shadowWidget->winId();
1368 shadows[0] = frameId();
1369 if (shadowWidget != NULL)
1370 shadows[1] = shadowWidget->winId();
1373 XRestackWindows(tqt_xdisplay(), shadows, 2);
1377 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1386void Client::removeShadow()
1388 TQValueList<ShadowRegion>::Iterator it;
1390 shadowDelayTimer->stop();
1392 if (shadowWidget != NULL) {
1393 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1394 if ((*it).client ==
this) {
1395 shadowRegions.remove(it);
1398 delete shadowWidget;
1399 shadowWidget = NULL;
1407TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1408 int h,
int thickness,
int xOffset,
int yOffset)
1410 TQRegion exposedRegion;
1412 exposedRegion = TQRegion(x, y, w, h);
1413 exposedRegion -= occludedRegion;
1415 if (thickness > 0) {
1418 TQMemArray<TQRect> occludedRects;
1419 TQMemArray<TQRect>::Iterator it, itEnd;
1420 TQRegion shadowRegion;
1422 occludedRects = occludedRegion.rects();
1423 itEnd = occludedRects.end();
1424 for (it = occludedRects.begin(); it != itEnd; ++it) {
1428 it->setTop(it->top() - thickness + yOffset);
1429 it->setLeft(it->left() - thickness + xOffset);
1430 it->setRight(it->right() + thickness + xOffset);
1431 it->setBottom(it->bottom() + thickness + yOffset);
1432 shadowRegion += TQRegion(*it);
1434 exposedRegion -= exposedRegion - shadowRegion;
1437 return exposedRegion;
1443void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1447 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1448 int subW, subH, w, x, y, zeroX, zeroY;
1450 TQMemArray<TQRect>::Iterator it, itEnd;
1451 TQMemArray<TQRect> rectangles;
1454 int thickness, windowX, windowY, xOffset, yOffset;
1456 rectangles = exposed.rects();
1457 rootWindow = tqt_xrootwin();
1458 thickness = options->shadowThickness(isActive());
1459 windowX = this->x();
1460 windowY = this->y();
1461 xOffset = options->shadowXOffset(isActive());
1462 yOffset = options->shadowYOffset(isActive());
1463 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1466 itEnd = rectangles.end();
1467 for (it = rectangles.begin(); it != itEnd; ++it) {
1468 subW = (*it).width();
1469 subH = (*it).height();
1470 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1472 zeroX = (*it).x() - windowX + thickness - xOffset;
1473 zeroY = (*it).y() - windowY + thickness - yOffset;
1474 image = subPixmap.convertToImage();
1476 for (x = 0; x < subW; x++) {
1477 for (y = 0; y < subH; y++) {
1478 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1479 pixel = image.pixel(x, y);
1480 pixelRed = tqRed(pixel);
1481 pixelGreen = tqGreen(pixel);
1482 pixelBlue = tqBlue(pixel);
1483 image.setPixel(x, y,
1484 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1485 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1486 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1490 subPixmap.convertFromImage(image);
1491 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1498void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1499 TQRegion exposed,
int thickness,
double maxOpacity)
1501 int distance, intersectCount, i, j, x, y;
1503 double decay, factor, opacity;
1504 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1505 int lineIntersects, maxIntersects, maxY;
1506 int irBottom, irLeft, irRight, irTop, yIncrement;
1507 int subW, subH, w, h, zeroX, zeroY;
1509 TQMemArray<TQRect>::Iterator it, itEnd;
1510 TQMemArray<TQRect> rectangles;
1513 int windowX, windowY, xOffset, yOffset;
1515 rectangles = exposed.rects();
1516 rootWindow = tqt_xrootwin();
1517 windowX = this->x();
1518 windowY = this->y();
1519 xOffset = options->shadowXOffset(isActive());
1520 yOffset = options->shadowYOffset(isActive());
1521 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1522 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1523 lineIntersects = thickness * 2 + 1;
1524 factor = maxIntersects / maxOpacity;
1525 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1527 h = pixmap.height();
1528 xOffset = options->shadowXOffset(isActive());
1529 yOffset = options->shadowYOffset(isActive());
1531 opacityCache->resize(0);
1532 opacityCache->resize(w * h);
1533 occluded.translate(-windowX + thickness, -windowY + thickness);
1535 itEnd = rectangles.end();
1536 for (it = rectangles.begin(); it != itEnd; ++it) {
1537 subW = (*it).width();
1538 subH = (*it).height();
1539 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1542 zeroX = (*it).x() - windowX + thickness - xOffset;
1543 zeroY = (*it).y() - windowY + thickness - yOffset;
1544 image = subPixmap.convertToImage();
1550 for (x = 0; x < subW; x++) {
1551 irLeft = zeroX + x - thickness;
1552 irRight = zeroX + x + thickness;
1557 irTop = zeroY + y - thickness * yIncrement;
1560 irBottom = zeroY + y + thickness * yIncrement;
1562 if (opacity == -1) {
1567 for (j = irTop; j != irBottom; j += yIncrement) {
1570 for (i = irLeft; i <= irRight; i++) {
1571 if (occluded.contains(TQPoint(i, j)))
1577 if (intersectCount < 0)
1580 for (i = irLeft; i <= irRight; i++) {
1581 if (occluded.contains(TQPoint(i, irBottom)))
1586 distance = maxIntersects - intersectCount;
1587 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1589 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1590 pixel = image.pixel(x, y);
1591 pixelRed = tqRed(pixel);
1592 pixelGreen = tqGreen(pixel);
1593 pixelBlue = tqBlue(pixel);
1594 image.setPixel(x, y,
1595 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1596 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1597 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1599 for (i = irLeft; i <= irRight; i++) {
1600 if (occluded.contains(TQPoint(i, irTop)))
1608 irTop += yIncrement;
1609 for (j = irTop; j != irBottom; j += yIncrement) {
1610 if (occluded.contains(TQPoint(irLeft, j)))
1614 for (j = irTop; j != irBottom; j += yIncrement) {
1615 if (occluded.contains(TQPoint(irRight, j)))
1628 subPixmap.convertFromImage(image);
1629 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1637void Client::setMappingState(
int s)
1639 assert( client != None );
1640 assert( !deleting || s == WithdrawnState );
1641 if( mapping_state == s )
1643 bool was_unmanaged = ( mapping_state == WithdrawnState );
1645 if( mapping_state == WithdrawnState )
1647 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1650 assert( s == NormalState || s == IconicState );
1652 unsigned long data[2];
1653 data[0] = (
unsigned long) s;
1654 data[1] = (
unsigned long) None;
1655 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1656 PropModeReplace, (
unsigned char *)data, 2);
1659 postponeGeometryUpdates(
false );
1666void Client::rawShow()
1668 if( decoration != NULL )
1669 decoration->widget()->show();
1670 XMapWindow( tqt_xdisplay(), frame );
1673 XMapWindow( tqt_xdisplay(), wrapper );
1674 XMapWindow( tqt_xdisplay(), client );
1676 if (options->shadowEnabled(isActive()))
1677 drawDelayedShadow();
1685void Client::rawHide()
1694 drawIntersectingShadows();
1695 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1696 XUnmapWindow( tqt_xdisplay(), frame );
1697 XUnmapWindow( tqt_xdisplay(), wrapper );
1698 XUnmapWindow( tqt_xdisplay(), client );
1699 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1700 if( decoration != NULL )
1701 decoration->widget()->hide();
1702 workspace()->clientHidden(
this );
1705void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1710 memset(&ev, 0,
sizeof(ev));
1711 ev.xclient.type = ClientMessage;
1712 ev.xclient.window = w;
1713 ev.xclient.message_type = a;
1714 ev.xclient.format = 32;
1715 ev.xclient.data.l[0] = protocol;
1716 ev.xclient.data.l[1] = get_tqt_x_time();
1717 ev.xclient.data.l[2] = data1;
1718 ev.xclient.data.l[3] = data2;
1719 ev.xclient.data.l[4] = data3;
1721 if (w == tqt_xrootwin())
1722 mask = SubstructureRedirectMask;
1723 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1729bool Client::isCloseable()
const
1731 if( isModalSystemNotification())
1733 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1746 if ( Pdeletewindow )
1748 Notify::raise( Notify::Close );
1749 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1766 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1769 Notify::raise( Notify::Close );
1772 Notify::raise( Notify::TransDelete );
1773 if( isNormalWindow())
1774 Notify::raise( Notify::Delete );
1775 killProcess(
false );
1777 XKillClient(tqt_xdisplay(), window() );
1784void Client::pingWindow()
1788 if( options->killPingTimeout == 0 )
1790 if( ping_timer != NULL )
1792 ping_timer =
new TQTimer(
this );
1793 connect( ping_timer, TQ_SIGNAL( timeout()), TQ_SLOT( pingTimeout()));
1794 ping_timer->start( options->killPingTimeout,
true );
1795 ping_timestamp = get_tqt_x_time();
1796 workspace()->sendPingToWindow( window(), ping_timestamp );
1799void Client::gotPing( Time timestamp )
1802 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1806 if( process_killer != NULL )
1808 process_killer->kill();
1809 delete process_killer;
1810 process_killer = NULL;
1814void Client::pingTimeout()
1816 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1819 killProcess(
true, ping_timestamp );
1822void Client::killProcess(
bool ask, Time timestamp )
1824 if( process_killer != NULL )
1826 Q_ASSERT( !ask || timestamp != CurrentTime );
1828 pid_t pid = info->pid();
1829 if( pid <= 0 || machine.isEmpty())
1831 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1834 if( machine !=
"localhost" )
1837 proc <<
"xon" << machine <<
"kill" << pid;
1838 proc.start( TDEProcess::DontCare );
1841 ::kill( pid, SIGTERM );
1845 process_killer =
new TDEProcess(
this );
1846 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1847 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1848 <<
"--windowname" <<
caption().utf8()
1849 <<
"--applicationname" << resourceClass()
1850 <<
"--wid" << TQCString().setNum( window())
1851 <<
"--timestamp" << TQCString().setNum( timestamp );
1852 connect( process_killer, TQ_SIGNAL( processExited( TDEProcess* )),
1853 TQ_SLOT( processKillerExited()));
1854 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1856 delete process_killer;
1857 process_killer = NULL;
1863bool Client::isSuspendable()
const
1865 bool cansuspend =
true;
1866 if( skipTaskbar() || skipPager() )
1869 pid_t pid = info->pid();
1870 if( pid <= 0 || machine.isEmpty())
1872 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1873 if( machine !=
"localhost" )
1880 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1882 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1884 if (procStatFile.open(IO_ReadOnly))
1886 TQByteArray statRaw = procStatFile.readAll();
1887 procStatFile.close();
1889 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1890 char tbuf[PATH_MAX];
1892 TQString state(TQChar(inf->pr_sname));
1894 readlink(TQString(
"/proc/%1/path/a.out").arg(pid).latin1(),
1895 tbuf,
sizeof(tbuf));
1896 tcomm = basename(tbuf);
1898 TQString statString(statRaw);
1899 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1900 TQString tcomm = statFields[1];
1901 TQString state = statFields[2];
1906 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1908 Client* nextclient = *it;
1909 pid_t nextpid = nextclient->info->pid();
1910 TQCString nextmachine = nextclient->wmClientMachine(
true );
1911 if( nextpid > 0 && (!nextmachine.isEmpty()))
1913 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1915 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1921 TQString execname(tcomm);
1922 execname.truncate(execname.length()-1);
1923 execname = execname.remove(0,1);
1925 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1942bool Client::isResumeable()
const
1945 pid_t pid = info->pid();
1946 if( pid <= 0 || machine.isEmpty())
1948 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1949 if( machine !=
"localhost" )
1956 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1958 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1960 if (procStatFile.open(IO_ReadOnly))
1962 TQByteArray statRaw = procStatFile.readAll();
1963 procStatFile.close();
1965 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1966 TQString state(TQChar(inf->pr_sname));
1968 TQString statString(statRaw);
1969 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1970 TQString tcomm = statFields[1];
1971 TQString state = statFields[2];
1989bool Client::queryUserSuspendedResume()
1993 if (process_resumer != NULL)
1998 process_resumer =
new TDEProcess(
this );
1999 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
2000 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
2001 <<
"--windowname" <<
caption().utf8()
2002 <<
"--applicationname" << resourceClass()
2003 <<
"--wid" << TQCString().setNum( window());
2004 connect( process_resumer, TQ_SIGNAL( processExited( TDEProcess* )),
2005 TQ_SLOT( processResumerExited()));
2006 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
2008 delete process_resumer;
2009 process_resumer = NULL;
2020void Client::suspendWindow()
2023 pid_t pid = info->pid();
2024 if( pid <= 0 || machine.isEmpty())
2026 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
2027 if( machine !=
"localhost" )
2033 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2035 Client* nextclient = *it;
2036 pid_t nextpid = nextclient->info->pid();
2037 TQCString nextmachine = nextclient->wmClientMachine(
true );
2038 if( nextpid > 0 && (!nextmachine.isEmpty()))
2040 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2042 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2043 nextclient->info->setVisibleName(newCaption.utf8());
2044 nextclient->info->setVisibleIconName(newCaption.utf8());
2045 nextclient->minimized_before_suspend = nextclient->isMinimized();
2046 nextclient->minimize(
true);
2050 ::kill( pid, SIGSTOP );
2054void Client::resumeWindow()
2057 pid_t pid = info->pid();
2058 if( pid <= 0 || machine.isEmpty())
2060 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2061 if( machine !=
"localhost" )
2067 ::kill( pid, SIGCONT );
2068 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2070 Client* nextclient = *it;
2071 pid_t nextpid = nextclient->info->pid();
2072 TQCString nextmachine = nextclient->wmClientMachine(
true );
2073 if( nextpid > 0 && (!nextmachine.isEmpty()))
2075 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2077 if (!nextclient->minimized_before_suspend)
2079 nextclient->unminimize(
true);
2081 nextclient->updateCaption();
2088void Client::processKillerExited()
2090 kdDebug( 1212 ) <<
"Killer exited" << endl;
2091 delete process_killer;
2092 process_killer = NULL;
2095void Client::processResumerExited()
2097 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2099 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2102 takeFocus( Allowed );
2104 delete process_resumer;
2105 process_resumer = NULL;
2108void Client::setSkipTaskbar(
bool b,
bool from_outside )
2110 int was_wants_tab_focus = wantsTabFocus();
2113 b = rules()->checkSkipTaskbar( b );
2114 original_skip_taskbar = b;
2116 if ( b == skipTaskbar() )
2119 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2120 updateWindowRules();
2121 if( was_wants_tab_focus != wantsTabFocus())
2122 workspace()->updateFocusChains(
this,
2123 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2126void Client::setSkipPager(
bool b )
2128 b = rules()->checkSkipPager( b );
2129 if ( b == skipPager() )
2132 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2133 updateWindowRules();
2136void Client::setModal(
bool m )
2147void Client::setDesktop(
int desktop )
2149 if(
desktop != NET::OnAllDesktops )
2150 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(),
desktop ));
2154 int was_desk = desk;
2157 if(( was_desk == NET::OnAllDesktops ) != (
desktop == NET::OnAllDesktops ))
2159 if ( isShown(
true ))
2160 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2161 workspace()->updateOnAllDesktopsOfTransients(
this );
2163 if( decoration != NULL )
2164 decoration->desktopChange();
2165 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2167 updateWindowRules();
2170void Client::setOnAllDesktops(
bool b )
2172 if(( b && isOnAllDesktops())
2173 || ( !b && !isOnAllDesktops()))
2176 setDesktop( NET::OnAllDesktops );
2178 setDesktop( workspace()->currentDesktop());
2181bool Client::isOnCurrentDesktop()
const
2183 return isOnDesktop( workspace()->currentDesktop());
2186int Client::screen()
const
2188 if( !options->xineramaEnabled )
2190 return workspace()->screenNumber( geometry().center());
2193bool Client::isOnScreen(
int screen )
const
2195 if( !options->xineramaEnabled )
2197 return workspace()->screenGeometry( screen ).intersects( geometry());
2201void Client::takeActivity(
int flags,
bool handled, allowed_t )
2203 if( !handled || !Ptakeactivity )
2205 if( flags & ActivityFocus )
2206 takeFocus( Allowed );
2207 if( flags & ActivityRaise )
2208 workspace()->raiseClient(
this );
2213 static Time previous_activity_timestamp;
2214 static Client* previous_client;
2215 if( previous_activity_timestamp == get_tqt_x_time() && previous_client !=
this )
2217 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2218 kdDebug( 1212 ) << kdBacktrace() << endl;
2220 previous_activity_timestamp = get_tqt_x_time();
2221 previous_client =
this;
2223 workspace()->sendTakeActivity(
this, get_tqt_x_time(), flags );
2227void Client::takeFocus( allowed_t )
2230 static Time previous_focus_timestamp;
2231 static Client* previous_client;
2232 if( previous_focus_timestamp == get_tqt_x_time() && previous_client !=
this )
2234 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2235 kdDebug( 1212 ) << kdBacktrace() << endl;
2237 previous_focus_timestamp = get_tqt_x_time();
2238 previous_client =
this;
2240 if ( rules()->checkAcceptFocus( input ))
2242 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, get_tqt_x_time() );
2246 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2248 workspace()->setShouldGetFocus(
this );
2260 if (isModalSystemNotification())
2262 return Pcontexthelp;
2276 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2277 TQWhatsThis::enterWhatsThisMode();
2286void Client::fetchName()
2288 setCaption( readName());
2291TQString Client::readName()
const
2293 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2294 return TQString::fromUtf8( info->name() );
2296 return KWin::readNameProperty( window(), XA_WM_NAME );
2299KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2301void Client::setCaption(
const TQString& s,
bool force )
2303 if ( s != cap_normal || force )
2305 bool reset_name = force;
2306 for(
unsigned int i = 0;
2309 if( !s[ i ].isPrint())
2312 bool was_suffix = ( !cap_suffix.isEmpty());
2313 TQString machine_suffix;
2316 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2317 cap_suffix = machine_suffix + shortcut_suffix;
2318 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2323 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2325 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2326 info->setVisibleName(
caption().utf8() );
2329 if(( (was_suffix && cap_suffix.isEmpty())
2332 info->setVisibleName(
"" );
2333 info->setVisibleIconName(
"" );
2335 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2336 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2338 if( isManaged() && decoration != NULL )
2339 decoration->captionChange();
2343void Client::updateCaption()
2345 setCaption( cap_normal,
true );
2348void Client::fetchIconicName()
2351 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2352 s = TQString::fromUtf8( info->iconName() );
2354 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2355 if ( s != cap_iconic )
2357 bool was_set = !cap_iconic.isEmpty();
2359 if( !cap_suffix.isEmpty())
2361 if( !cap_iconic.isEmpty())
2362 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2364 info->setVisibleIconName(
"" );
2373 return full ? cap_normal + cap_suffix : cap_normal;
2376void Client::getWMHints()
2378 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2380 window_group = None;
2384 if( hints->flags & InputHint )
2385 input = hints->input;
2386 if( hints->flags & WindowGroupHint )
2387 window_group = hints->window_group;
2388 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2389 XFree( (
char*)hints );
2393 updateAllowedActions();
2396void Client::getMotifHints()
2398 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2399 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2400 motif_noborder = mnoborder;
2401 if( !hasNETSupport())
2403 motif_may_resize = mresize;
2404 motif_may_move = mmove;
2407 motif_may_resize = motif_may_move =
true;
2410 motif_may_close = mclose;
2412 updateDecoration(
true );
2415void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2419 *icon = KWin::icon( win, 32, 32,
true, KWin::NETWM | KWin::WMHints );
2420 if( miniicon != NULL )
2422 if( icon == NULL || !icon->isNull())
2423 *miniicon = KWin::icon( win, 16, 16,
true, KWin::NETWM | KWin::WMHints );
2425 *miniicon = TQPixmap();
2429void Client::getIcons()
2432 readIcons( window(), &icon_pix, &miniicon_pix );
2433 if( icon_pix.isNull())
2435 icon_pix = group()->icon();
2436 miniicon_pix = group()->miniIcon();
2438 if( icon_pix.isNull() && isTransient())
2440 ClientList mainclients = mainClients();
2441 for( ClientList::ConstIterator it = mainclients.begin();
2442 it != mainclients.end() && icon_pix.isNull();
2445 icon_pix = (*it)->icon();
2446 miniicon_pix = (*it)->miniIcon();
2449 if( icon_pix.isNull())
2451 icon_pix = KWin::icon( window(), 32, 32,
true, KWin::ClassHint | KWin::XApp );
2452 miniicon_pix = KWin::icon( window(), 16, 16,
true, KWin::ClassHint | KWin::XApp );
2454 if( isManaged() && decoration != NULL )
2455 decoration->iconChange();
2458void Client::getWindowProtocols()
2469 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2471 for (i = 0; i < n; i++)
2472 if (p[i] == atoms->wm_delete_window)
2474 else if (p[i] == atoms->wm_take_focus)
2476 else if (p[i] == atoms->net_wm_take_activity)
2478 else if (p[i] == atoms->net_wm_context_help)
2480 else if (p[i] == atoms->net_wm_ping)
2487static int nullErrorHandler(Display *, XErrorEvent *)
2497 return getStringProperty(w, tqt_window_role).lower();
2505 return getStringProperty(w, tqt_sm_client_id);
2513 return getStringProperty(w, XA_WM_COMMAND,
' ');
2523 unsigned long nitems = 0;
2524 unsigned long extra = 0;
2525 unsigned char *data = 0;
2527 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2528 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2529 False, XA_WINDOW, &type, &format,
2530 &nitems, &extra, &data );
2531 XSetErrorHandler(oldHandler);
2532 if (status == Success )
2534 if (data && nitems > 0)
2535 result = *((Window*) data);
2542void Client::getWmClientLeader()
2554 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2566 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2571void Client::getWmClientMachine()
2573 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2574 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2575 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2576 if( client_machine.isEmpty())
2577 client_machine =
"localhost";
2586 TQCString result = client_machine;
2589 if( result !=
"localhost" && isLocalMachine( result ))
2590 result =
"localhost";
2601 if (wmClientLeaderWin)
2602 return wmClientLeaderWin;
2606bool Client::wantsTabFocus()
const
2608 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2612bool Client::wantsInput()
const
2614 return rules()->checkAcceptFocus( input || Ptakefocus );
2617bool Client::isDesktop()
const
2619 return windowType() == NET::Desktop;
2622bool Client::isDock()
const
2624 return windowType() == NET::Dock;
2627bool Client::isTopMenu()
const
2629 return windowType() == NET::TopMenu;
2633bool Client::isMenu()
const
2635 return windowType() == NET::Menu && !isTopMenu();
2638bool Client::isToolbar()
const
2640 return windowType() == NET::Toolbar;
2643bool Client::isSplash()
const
2645 return windowType() == NET::Splash;
2648bool Client::isUtility()
const
2650 return windowType() == NET::Utility;
2653bool Client::isDialog()
const
2655 return windowType() == NET::Dialog;
2658bool Client::isNormalWindow()
const
2660 return windowType() == NET::Normal;
2663bool Client::isSpecialWindow()
const
2665 return isDesktop() || isDock() || isSplash() || isTopMenu()
2669NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2671 NET::WindowType wt = info->windowType( supported_types );
2674 NET::WindowType wt2 = rules()->checkType( wt );
2678 info->setWindowType( wt );
2681 if( wt == NET::Menu )
2686 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2687 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2691 const char*
const oo_prefix =
"openoffice.org";
2693 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2695 if( wt == NET::Unknown )
2696 wt = isTransient() ? NET::Dialog : NET::Normal;
2704void Client::setCursor( Position m )
2712 case PositionTopLeft:
2713 case PositionBottomRight:
2714 setCursor( TQt::sizeFDiagCursor );
2716 case PositionBottomLeft:
2717 case PositionTopRight:
2718 setCursor( TQt::sizeBDiagCursor );
2721 case PositionBottom:
2722 setCursor( TQt::sizeVerCursor );
2726 setCursor( TQt::sizeHorCursor );
2730 setCursor( TQt::sizeAllCursor );
2732 setCursor( TQt::arrowCursor );
2739void Client::setCursor(
const TQCursor& c )
2741 if( c.handle() == cursor.handle())
2744 if( decoration != NULL )
2745 decoration->widget()->setCursor( cursor );
2746 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2749Client::Position Client::mousePosition(
const TQPoint& p )
const
2751 if( decoration != NULL )
2752 return decoration->mousePosition( p );
2753 return PositionCenter;
2756void Client::updateAllowedActions(
bool force )
2758 if( !isManaged() && !force )
2760 unsigned long old_allowed_actions = allowed_actions;
2761 allowed_actions = 0;
2763 allowed_actions |= NET::ActionMove;
2765 allowed_actions |= NET::ActionResize;
2767 allowed_actions |= NET::ActionMinimize;
2769 allowed_actions |= NET::ActionShade;
2771 if( isMaximizable())
2772 allowed_actions |= NET::ActionMax;
2773 if( userCanSetFullScreen())
2774 allowed_actions |= NET::ActionFullScreen;
2775 allowed_actions |= NET::ActionChangeDesktop;
2777 allowed_actions |= NET::ActionClose;
2778 if( old_allowed_actions == allowed_actions )
2781 info->setAllowedActions( allowed_actions );
2785void Client::autoRaise()
2787 workspace()->raiseClient(
this );
2791void Client::cancelAutoRaise()
2793 delete autoRaiseTimer;
2797void Client::setOpacity(uint opacity)
2802 if (opacity == Opacity::Opaque && !custom_opacity)
2804 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2805 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2808 if(opacity == opacity_)
2810 long data = opacity;
2811 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2812 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2817void Client::setShadowSize(uint shadowSize)
2821 long data = shadowSize;
2822 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2825uint Client::defaultOpacity()
2827 return defaultOpacity(isActive() || (
keepAbove() && options->keepAboveAsActive));
2830uint Client::defaultOpacity(
bool active)
2834 if( ruleOpacityActive() )
2835 return rule_opacity_active;
2837 return options->translucentActiveWindows ? options->activeWindowOpacity : Opacity::Opaque;
2841 if( ruleOpacityInactive() )
2842 return rule_opacity_inactive;
2844 return options->translucentInactiveWindows ? options->inactiveWindowOpacity : Opacity::Opaque;
2848void Client::updateOpacity()
2851 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2853 uint opacity = defaultOpacity();
2854 setOpacity(opacity);
2859 ClientList tmpGroupMembers = group()->members();
2860 ClientList groupMembers;
2861 groupMembers.append(
this);
2862 tmpGroupMembers.remove(
this);
2863 ClientList::Iterator it = tmpGroupMembers.begin();
2864 while (it != tmpGroupMembers.end())
2867 if ((*it) !=
this && (*it)->isBMP())
2871 if ((*it)->touches(
this))
2874 (*it)->setOpacity(opacity);
2876 (*it)->setShadowSize(options->activeWindowShadowSize);
2877 groupMembers.append(*it);
2878 tmpGroupMembers.remove(it);
2879 it = tmpGroupMembers.begin();
2885 for( ClientList::ConstIterator it2 = groupMembers.begin(); it2 != groupMembers.end(); it2++ )
2887 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2890 (*it)->setOpacity(opacity);
2891 (*it)->setShadowSize(isActive() ? options->activeWindowShadowSize : options->inactiveWindowShadowSize);
2892 groupMembers.append(*it);
2893 tmpGroupMembers.remove(it);
2894 it = tmpGroupMembers.begin();
2900 if (found)
continue;
2906 else if (isNormalWindow())
2909 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2910 if ((*it)->isUtility() || ((*it)->isDialog() && isActive() ))
2911 (*it)->setOpacity(opacity);
2915void Client::updateShadowSize()
2918 if (!(isNormalWindow() || isDialog() || isUtility() ))
2921 setShadowSize(options->activeWindowShadowSize);
2923 setShadowSize(options->inactiveWindowShadowSize);
2926uint Client::ruleOpacityInactive()
2928 return rule_opacity_inactive;
2931uint Client::ruleOpacityActive()
2933 return rule_opacity_active;
2936bool Client::getWindowOpacity()
2938 unsigned char *data = 0;
2941 unsigned long n, left;
2942 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
2943 if (result == Success && data && format == 32 )
2945 opacity_ = *
reinterpret_cast< long*
>( data );
2949 if ( !(Workspace::self()->initializing()
2950 && ( opacity_ == defaultOpacity(
false)
2951 || opacity_ == defaultOpacity(
true) ) ) )
2953 custom_opacity =
true;
2956 XFree ((
char*)data);
2962void Client::setCustomOpacityFlag(
bool custom)
2964 custom_opacity = custom;
2967uint Client::opacity()
2972int Client::opacityPercentage()
2974 return opacity_ / ( 0xffffffff / 100 );
2977bool Client::touches(
const Client* c)
2980 if (y() == c->y() + c->height())
2982 if (y() + height() == c->y())
2984 if (x() == c->x() + c->width())
2986 if (x() + width() == c->x())
2992kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
2995 return stream <<
"\'NULL_CLIENT\'";
2996 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
2998kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
3002 for( ClientList::ConstIterator it = list.begin();
3014kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3018 for( ConstClientList::ConstIterator it = list.begin();
3032TQPixmap * twin_get_menu_pix_hack()
3036 p = SmallIcon(
"bx2" );
3042#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)