16#include <tqapplication.h>
18#include <tqdatetime.h>
21#include <tdeprocess.h>
23#include <tdestandarddirs.h>
24#include <tqwhatsthis.h>
26#include <kiconloader.h>
39#include "notifications.h"
42#include <X11/extensions/shape.h>
47extern Atom tqt_wm_state;
48extern Atom tqt_window_role;
49extern Atom tqt_sm_client_id;
52static const int SHADOW_DELAY = 200;
68static TQValueList<ShadowRegion> shadowRegions;
101 bridge( new Bridge( this )),
102 inhibitConfigureRequests(false),
103 move_faked_activity( false ),
104 move_resize_grab_window( None ),
105 transient_for( NULL ),
106 transient_for_id( None ),
107 original_transient_for_id( None ),
109 window_group( None ),
110 in_layer( UnknownLayer ),
112 process_killer( NULL ),
113 process_resumer( NULL ),
114 user_time( CurrentTime ),
115 allowed_actions( 0 ),
116 postpone_geometry_updates( 0 ),
117 pending_geometry_update( false ),
118 shade_geometry_change( false ),
123 opacity_( Opacity::Opaque ),
124 demandAttentionKNotifyTimer( NULL ),
125 activeMaximizing(false),
132 configureRequestTimer =
new TQTimer(
this);
133 connect(configureRequestTimer, TQ_SIGNAL(timeout()), TQ_SLOT(configureRequestTimeout()));
135 shadowDelayTimer =
new TQTimer(
this);
136 opacityCache = &activeOpacityCache;
137 shadowAfterClient = NULL;
140 connect(shadowDelayTimer, TQ_SIGNAL(timeout()), TQ_SLOT(drawShadow()));
143 mapping_state = WithdrawnState;
146 mode = PositionCenter;
148 moveResizeMode =
false;
152 shade_mode = ShadeNone;
158 motif_noborder =
false;
159 motif_may_move =
true;
160 motif_may_resize =
true;
161 motif_may_close =
true;
162 fullscreen_mode = FullScreenNone;
163 skip_taskbar =
false;
164 original_skip_taskbar =
false;
169 user_noborder =
false;
170 user_noborder_forced =
false;
172 ignore_focus_stealing =
false;
173 demands_attention =
false;
174 check_active_modal =
false;
184 max_mode = MaximizeRestore;
185 maxmode_restore = MaximizeRestore;
189 frame_geometry = TQRect( 0, 0, 100, 100 );
190 client_size = TQSize( 100, 100 );
191 custom_opacity =
false;
192 rule_opacity_active = 0;
193 rule_opacity_inactive = 0;
203 assert(!moveResizeMode);
204 assert( client == None );
205 assert( frame == None && wrapper == None );
206 assert( decoration == NULL );
207 assert( postpone_geometry_updates == 0 );
208 assert( !check_active_modal );
214void Client::deleteClient( Client* c, allowed_t )
226 workspace()->discardUsedWindowRules(
this,
true );
227 StackingUpdatesBlocker blocker( workspace());
228 if (!custom_opacity) setOpacity(Opacity::Opaque);
232 drawIntersectingShadows();
234 ++postpone_geometry_updates;
238 setMappingState( WithdrawnState );
242 workspace()->clientHidden(
this );
243 XUnmapWindow( tqt_xdisplay(), frameId());
248 workspace()->removeClient(
this, Allowed );
251 info->setDesktop( 0 );
253 info->setState( 0, info->state());
255 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
256 XDeleteProperty( tqt_xdisplay(), client, atoms->net_frame_extents );
257 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
258 XReparentWindow( tqt_xdisplay(), client, workspace()->rootWin(), x(), y());
259 XRemoveFromSaveSet( tqt_xdisplay(), client );
260 XSelectInput( tqt_xdisplay(), client, NoEventMask );
263 XMapWindow( tqt_xdisplay(), client );
270 XUnmapWindow( tqt_xdisplay(), client );
273 XDestroyWindow( tqt_xdisplay(), wrapper );
275 XDestroyWindow( tqt_xdisplay(), frame );
277 --postpone_geometry_updates;
278 checkNonExistentClients();
279 deleteClient(
this, Allowed );
285void Client::destroyClient()
289 workspace()->discardUsedWindowRules(
this,
true );
290 StackingUpdatesBlocker blocker( workspace());
294 drawIntersectingShadows();
296 ++postpone_geometry_updates;
299 workspace()->clientHidden(
this );
302 workspace()->removeClient(
this, Allowed );
304 XDestroyWindow( tqt_xdisplay(), wrapper );
306 XDestroyWindow( tqt_xdisplay(), frame );
308 --postpone_geometry_updates;
309 checkNonExistentClients();
310 deleteClient(
this, Allowed );
313void Client::updateDecoration(
bool check_workspace_pos,
bool force )
315 if( !force && (( decoration == NULL && noBorder())
316 || ( decoration != NULL && !noBorder())))
318 bool do_show =
false;
319 postponeGeometryUpdates(
true );
324 setMask( TQRegion());
325 decoration = workspace()->createDecoration( bridge );
328 decoration->widget()->installEventFilter(
this );
329 XReparentWindow( tqt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
330 decoration->widget()->lower();
331 decoration->borders( border_left, border_right, border_top, border_bottom );
332 int save_workarea_diff_x = workarea_diff_x;
333 int save_workarea_diff_y = workarea_diff_y;
334 move( calculateGravitation(
false ));
335 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
336 workarea_diff_x = save_workarea_diff_x;
337 workarea_diff_y = save_workarea_diff_y;
342 if( check_workspace_pos )
343 checkWorkspacePosition();
344 postponeGeometryUpdates(
false );
346 decoration->widget()->show();
347 updateFrameExtents();
348 updateOpacityCache();
351void Client::destroyDecoration()
353 if( decoration != NULL )
357 TQPoint grav = calculateGravitation(
true );
358 border_left = border_right = border_top = border_bottom = 0;
359 setMask( TQRegion());
360 int save_workarea_diff_x = workarea_diff_x;
361 int save_workarea_diff_y = workarea_diff_y;
362 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
364 workarea_diff_x = save_workarea_diff_x;
365 workarea_diff_y = save_workarea_diff_y;
369void Client::checkBorderSizes()
371 if( decoration == NULL )
373 int new_left, new_right, new_top, new_bottom;
374 decoration->borders( new_left, new_right, new_top, new_bottom );
375 if( new_left == border_left && new_right == border_right
376 && new_top == border_top && new_bottom == border_bottom )
378 GeometryUpdatesPostponer blocker(
this );
379 move( calculateGravitation(
true ));
380 border_left = new_left;
381 border_right = new_right;
382 border_top = new_top;
383 border_bottom = new_bottom;
384 if (border_left != new_left ||
385 border_right != new_right ||
386 border_top != new_top ||
387 border_bottom != new_bottom)
388 move( calculateGravitation(
false ));
389 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
390 checkWorkspacePosition();
393void Client::detectNoBorder()
395 if( Shape::hasShape( window()))
400 switch( windowType())
422 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
426void Client::detectShapable()
428 if( Shape::hasShape( window()))
430 switch( windowType())
450void Client::updateFrameExtents()
453 strut.left = border_left;
454 strut.right = border_right;
455 strut.top = border_top;
456 strut.bottom = border_bottom;
457 info->setFrameExtents( strut );
465void Client::resizeDecoration(
const TQSize& s )
467 if( decoration == NULL )
469 TQSize oldsize = decoration->widget()->size();
470 decoration->resize( s );
473 TQResizeEvent e( s, oldsize );
474 TQApplication::sendEvent( decoration->widget(), &e );
476 if (!moveResizeMode && options->shadowEnabled(isActive()))
480 updateOpacityCache();
484bool Client::noBorder()
const
486 return noborder || isFullScreen() || user_noborder || ( !user_noborder_forced && motif_noborder );
489bool Client::userCanSetNoBorder()
const
491 return !noborder && !isFullScreen() && !isShade();
494bool Client::isUserNoBorder()
const
496 return user_noborder;
499void Client::setUserNoBorder(
bool set )
501 setUserNoBorder(set,
true);
504void Client::setUserNoBorder(
bool set,
bool forced )
506 if( !userCanSetNoBorder())
508 auto noBorderApply = rules()->applyNoBorder( set );
509 set = noBorderApply.value;
510 forced |= noBorderApply.wasApplied;
512 if( user_noborder == set && user_noborder_forced == forced )
515 user_noborder_forced = forced;
516 updateDecoration(
true,
false );
520bool Client::isUserNoBorderForced()
const
522 return user_noborder_forced;
525bool Client::isModalSystemNotification()
const
527 unsigned char *data = 0;
530 unsigned long n, left;
531 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
532 if (result == Success && data && format == 32 )
539void Client::updateShape()
542 if( shape() && !noBorder())
545 updateDecoration(
true );
547 updateOpacityCache();
550 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
551 clientPos().x(), clientPos().y(),
552 window(), ShapeBounding, ShapeSet);
558 if( Shape::version() >= 0x11 )
568 static Window helper_window = None;
569 if( helper_window == None )
570 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
571 0, 0, 1, 1, 0, 0, 0 );
572 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
573 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
574 frameId(), ShapeBounding, ShapeSet );
575 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
576 clientPos().x(), clientPos().y(),
577 window(), ShapeBounding, ShapeSubtract );
578 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
579 clientPos().x(), clientPos().y(),
580 window(), ShapeInput, ShapeUnion );
581 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
582 helper_window, ShapeInput, ShapeSet );
586void Client::setMask(
const TQRegion& reg,
int mode )
590 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
592 else if( mode == X::Unsorted )
593 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
594 reg.handle(), ShapeSet );
597 TQMemArray< TQRect > rects = reg.rects();
598 XRectangle* xrects =
new XRectangle[ rects.count() ];
599 for(
unsigned int i = 0;
603 xrects[ i ].x = rects[ i ].x();
604 xrects[ i ].y = rects[ i ].y();
605 xrects[ i ].width = rects[ i ].width();
606 xrects[ i ].height = rects[ i ].height();
608 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
609 xrects, rects.count(), ShapeSet, mode );
615TQRegion Client::mask()
const
618 return TQRegion( 0, 0, width(), height());
622void Client::setShapable(
bool b)
625 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
628void Client::hideClient(
bool hide )
641 if( isSpecialWindow())
643 if( isModalSystemNotification())
647 bool shown_mainwindow =
false;
648 ClientList mainclients = mainClients();
649 for( ClientList::ConstIterator it = mainclients.begin();
650 it != mainclients.end();
653 if( (*it)->isShown(
true ))
654 shown_mainwindow =
true;
656 if( !shown_mainwindow )
662 if( transientFor() != NULL )
664 if( !wantsTabFocus())
674 if( isModalSystemNotification())
688 info->setState(0, NET::Shaded);
690 Notify::raise( Notify::Minimize );
693 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
694 animateMinimizeOrUnminimize(
true );
699 updateAllowedActions();
700 workspace()->updateMinimizedOfTransients(
this );
702 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
705void Client::unminimize(
bool avoid_animation )
707 if (!queryUserSuspendedResume())
714 info->setState(NET::Shaded, NET::Shaded);
716 Notify::raise( Notify::UnMinimize );
718 if( isOnCurrentDesktop() && isShown(
true ))
720 if( mainClients().isEmpty() && !avoid_animation )
721 animateMinimizeOrUnminimize(
false );
724 updateAllowedActions();
725 workspace()->updateMinimizedOfTransients(
this );
729extern bool blockAnimation;
731void Client::animateMinimizeOrUnminimize(
bool minimize )
733 if ( blockAnimation )
735 if ( !options->animateMinimize )
738 if( decoration != NULL && decoration->animateMinimize(
minimize ))
745 float lf,rf,tf,bf,step;
747 int speed = options->animateMinimizeSpeed;
753 step = 40. * (11 - speed );
755 NETRect r = info->iconGeometry();
756 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
757 if ( !icongeom.isValid() )
760 TQPixmap pm = animationPixmap(
minimize ? width() : icongeom.width() );
762 TQRect before, after;
765 before = TQRect( x(), y(), width(), pm.height() );
766 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
770 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
771 after = TQRect( x(), y(), width(), pm.height() );
774 lf = (after.left() - before.left())/step;
775 rf = (after.right() - before.right())/step;
776 tf = (after.top() - before.top())/step;
777 bf = (after.bottom() - before.bottom())/step;
781 TQRect area = before;
789 TQPainter p ( workspace()->desktopWidget() );
790 bool need_to_clear =
false;
796 pm = animationPixmap( area.width() );
797 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
798 p.drawPixmap( area.x(), area.y(), pm );
801 p.drawPixmap( area2.x(), area2.y(), pm3 );
802 need_to_clear =
false;
806 XFlush(tqt_xdisplay());
807 XSync( tqt_xdisplay(), False );
811 area.setLeft(before.left() +
int(diff*lf));
812 area.setRight(before.right() +
int(diff*rf));
813 area.setTop(before.top() +
int(diff*tf));
814 area.setBottom(before.bottom() +
int(diff*bf));
817 if ( area2.intersects( area ) )
818 p.drawPixmap( area2.x(), area2.y(), pm2 );
822 need_to_clear =
true;
825 }
while ( t.elapsed() < step);
826 if (area2 == area || need_to_clear )
827 p.drawPixmap( area2.x(), area2.y(), pm2 );
837TQPixmap Client::animationPixmap(
int w )
839 TQFont font = options->font(isActive());
840 TQFontMetrics fm( font );
841 TQPixmap pm( w, fm.lineSpacing() );
842 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
844 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
845 p.setFont(options->font(isActive()));
846 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
851bool Client::isShadeable()
const
853 return !isSpecialWindow() && !noBorder();
856void Client::setShade( ShadeMode mode )
860 if( isModalSystemNotification())
862 mode = rules()->checkShade( mode );
863 if( shade_mode == mode )
865 bool was_shade = isShade();
866 ShadeMode was_shade_mode = shade_mode;
868 if( was_shade == isShade())
870 if( decoration != NULL )
871 decoration->shadeChange();
875 if( shade_mode == ShadeNormal )
877 if ( isShown(
true ) && isOnCurrentDesktop())
878 Notify::raise( Notify::ShadeUp );
880 else if( shade_mode == ShadeNone )
882 if( isShown(
true ) && isOnCurrentDesktop())
883 Notify::raise( Notify::ShadeDown );
886 assert( decoration != NULL );
887 GeometryUpdatesPostponer blocker(
this );
889 decoration->borders( border_left, border_right, border_top, border_bottom );
891 int as = options->animateShade? 10 : 1;
897 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
900 shade_geometry_change =
true;
901 TQSize s( sizeForClientSize( TQSize( clientSize())));
902 s.setHeight( border_top + border_bottom );
903 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
904 XUnmapWindow( tqt_xdisplay(), wrapper );
905 XUnmapWindow( tqt_xdisplay(), client );
906 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
912 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
916 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
917 resizeDecoration( TQSize( s.width(), h ));
918 TQApplication::syncX();
919 }
while ( h > s.height() + step );
923 shade_geometry_change =
false;
926 if( was_shade_mode == ShadeHover )
927 workspace()->activateNextClient(
this );
929 workspace()->focusToNull();
933 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
938 shade_geometry_change =
true;
939 TQSize s( sizeForClientSize( clientSize()));
942 int step = TQMAX( 4, TQABS( h - s.height() ) / as )+1;
946 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
947 resizeDecoration( TQSize( s.width(), h ));
951 TQApplication::syncX();
952 }
while ( h < s.height() - step );
955 shade_geometry_change =
false;
957 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
959 XMapWindow( tqt_xdisplay(), wrapperId());
960 XMapWindow( tqt_xdisplay(), window());
961 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
962 if (options->shadowEnabled(
false))
964 for (ClientList::ConstIterator it = transients().begin();
965 it != transients().end(); ++it)
967 (*it)->removeShadow();
968 (*it)->drawDelayedShadow();
973 workspace()->requestFocus(
this );
975 checkMaximizeGeometry();
976 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
977 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
979 updateAllowedActions();
980 workspace()->updateMinimizedOfTransients(
this );
981 decoration->shadeChange();
985void Client::configureRequestTimeout()
987 inhibitConfigureRequests =
false;
988 sendSyntheticConfigureNotify();
991void Client::shadeHover()
993 setShade( ShadeHover );
997void Client::cancelShadeHover()
999 delete shadeHoverTimer;
1000 shadeHoverTimer = 0;
1003void Client::toggleShade()
1006 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
1009void Client::updateVisibility()
1016 setMappingState( IconicState );
1017 info->setState( NET::Hidden, NET::Hidden );
1018 setSkipTaskbar(
true,
false );
1024 setSkipTaskbar( original_skip_taskbar,
false );
1028 setMappingState( IconicState );
1029 info->setState( NET::Hidden, NET::Hidden );
1034 info->setState( 0, NET::Hidden );
1035 if( !isOnCurrentDesktop())
1037 setMappingState( IconicState );
1043 bool belongs_to_desktop =
false;
1044 for( ClientList::ConstIterator it = group()->members().begin();
1045 it != group()->members().end();
1047 if( (*it)->isDesktop())
1049 belongs_to_desktop =
true;
1052 if( !belongs_to_desktop && workspace()->showingDesktop())
1053 workspace()->resetShowingDesktop(
true );
1055 setMappingState( IconicState );
1057 setMappingState( NormalState );
1062void Client::setShadowed(
bool shadowed)
1066 wasShadowed = isShadowed();
1067 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1077 if (!activeOpacityCache.isNull())
1078 activeOpacityCache.resize(0);
1079 if (!inactiveOpacityCache.isNull())
1080 inactiveOpacityCache.resize(0);
1085void Client::updateOpacityCache()
1087 if (!activeOpacityCache.isNull())
1088 activeOpacityCache.resize(0);
1089 if (!inactiveOpacityCache.isNull())
1090 inactiveOpacityCache.resize(0);
1092 if (!moveResizeMode) {
1096 drawIntersectingShadows();
1097 if (options->shadowEnabled(isActive()))
1098 drawDelayedShadow();
1106void Client::drawIntersectingShadows() {
1110 TQValueList<Client *> reshadowClients;
1111 TQValueListIterator<ShadowRegion> it;
1112 TQValueListIterator<Client *> it2;
1114 if (!options->shadowEnabled(
false))
1119 region = shapeBoundingRegion;
1124 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1125 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1126 !(*it).region.intersect(region).isEmpty())
1127 reshadowClients.append((*it).client);
1130 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1132 (*it2)->removeShadow();
1133 (*it2)->drawDelayedShadow();
1142void Client::drawOverlappingShadows(
bool waitForMe)
1146 TQValueList<Client *> reshadowClients;
1147 ClientList stacking_order;
1148 ClientList::ConstIterator it;
1149 TQValueListIterator<ShadowRegion> it2;
1150 TQValueListIterator<Client *> it3;
1152 if (!options->shadowEnabled(
false))
1157 region = shapeBoundingRegion;
1159 stacking_order = workspace()->stackingOrder();
1160 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1166 while (it != stacking_order.end()) {
1167 if ((*it)->windowType() == NET::Dock) {
1178 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1179 if ((*it2).client == (*it)) {
1180 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1181 && !(*it2).region.intersect(region).isEmpty())
1182 reshadowClients.append((*it2).client);
1189 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1190 (*it3)->removeShadow();
1191 if (it3 == reshadowClients.begin()) {
1193 (*it3)->drawShadowAfter(
this);
1195 (*it3)->drawDelayedShadow();
1201 (*it3)->drawShadowAfter(aClient);
1210void Client::drawDelayedShadow()
1212 shadowDelayTimer->stop();
1213 shadowDelayTimer->start(SHADOW_DELAY,
true);
1219void Client::drawShadowAfter(Client *after)
1221 shadowAfterClient = after;
1222 connect(after, TQ_SIGNAL(shadowDrawn()), TQ_SLOT(drawShadow()));
1228void Client::drawShadow()
1232 int i, count, ordering;
1235 if (shadowAfterClient != NULL) {
1236 disconnect(shadowAfterClient, TQ_SIGNAL(shadowDrawn()),
this, TQ_SLOT(drawShadow()));
1237 shadowAfterClient = NULL;
1240 if (!isOnCurrentDesktop())
1247 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1251 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1253 shapeBoundingRegion = TQRegion();
1254 for (i = 0; i < count; i++) {
1256 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1258 shapeBoundingRegion += shapeRectangle;
1264 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1265 shapeBoundingRegion.translate(x(), y());
1268 if (!isShadowed() || hidden || isMinimized() ||
1269 maximizeMode() == MaximizeFull ||
1270 !options->shadowWindowType(windowType())) {
1282 TQMemArray<TQRgb> pixelData;
1283 TQPixmap shadowPixmap;
1285 TQRegion exposedRegion;
1286 ShadowRegion shadowRegion;
1287 int thickness, xOffset, yOffset;
1289 thickness = options->shadowThickness(isActive());
1290 xOffset = options->shadowXOffset(isActive());
1291 yOffset = options->shadowYOffset(isActive());
1292 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1294 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1295 width() + thickness * 2, height() + thickness * 2);
1296 shadowPixmap.resize(shadow.size());
1299 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1300 shadowWidget->setGeometry(shadow);
1301 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1302 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1303 shadowWidget->installEventFilter(
this);
1307 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1308 shadow.y(), shadow.width(), shadow.height(), thickness,
1310 shadowRegion.region = exposedRegion;
1311 shadowRegion.client =
this;
1312 shadowRegions.append(shadowRegion);
1314 if (opacityCache->isNull())
1315 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1316 exposedRegion, thickness,
1317 options->shadowOpacity(isActive()));
1319 imposeCachedShadow(shadowPixmap, exposedRegion);
1322 TQMemArray<TQRect> exposedRects;
1323 TQMemArray<TQRect>::Iterator it, itEnd;
1324 XRectangle *shadowShapes;
1326 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1327 shadow.y(), shadow.width(), shadow.height(), thickness,
1329 shadowRegion.region = exposedRegion;
1330 shadowRegion.client =
this;
1331 shadowRegions.append(shadowRegion);
1334 exposedRects = exposedRegion.rects();
1336 itEnd = exposedRects.end();
1337 shadowShapes =
new XRectangle[exposedRects.count()];
1338 for (it = exposedRects.begin(); it != itEnd; ++it) {
1339 shadowShapes[i].x = (*it).x();
1340 shadowShapes[i].y = (*it).y();
1341 shadowShapes[i].width = (*it).width();
1342 shadowShapes[i].height = (*it).height();
1345 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1346 ShapeBounding, -x() + thickness - xOffset,
1347 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1349 delete [] shadowShapes;
1351 if (opacityCache->isNull())
1352 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1353 exposedRegion, thickness,
1354 options->shadowOpacity(isActive()));
1356 imposeCachedShadow(shadowPixmap, exposedRegion);
1363 shadowWidget->setErasePixmap(shadowPixmap);
1368 ClientList stacking_order = workspace()->stackingOrder();
1369 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1370 if ((*it)->isDesktop())
1373 shadows[0] = (*it)->frameId();
1374 shadows[1] = shadowWidget->winId();
1378 shadows[0] = frameId();
1379 if (shadowWidget != NULL)
1380 shadows[1] = shadowWidget->winId();
1383 XRestackWindows(tqt_xdisplay(), shadows, 2);
1387 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1396void Client::removeShadow()
1398 TQValueList<ShadowRegion>::Iterator it;
1400 shadowDelayTimer->stop();
1402 if (shadowWidget != NULL) {
1403 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1404 if ((*it).client ==
this) {
1405 shadowRegions.remove(it);
1408 delete shadowWidget;
1409 shadowWidget = NULL;
1417TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1418 int h,
int thickness,
int xOffset,
int yOffset)
1420 TQRegion exposedRegion;
1422 exposedRegion = TQRegion(x, y, w, h);
1423 exposedRegion -= occludedRegion;
1425 if (thickness > 0) {
1428 TQMemArray<TQRect> occludedRects;
1429 TQMemArray<TQRect>::Iterator it, itEnd;
1430 TQRegion shadowRegion;
1432 occludedRects = occludedRegion.rects();
1433 itEnd = occludedRects.end();
1434 for (it = occludedRects.begin(); it != itEnd; ++it) {
1438 it->setTop(it->top() - thickness + yOffset);
1439 it->setLeft(it->left() - thickness + xOffset);
1440 it->setRight(it->right() + thickness + xOffset);
1441 it->setBottom(it->bottom() + thickness + yOffset);
1442 shadowRegion += TQRegion(*it);
1444 exposedRegion -= exposedRegion - shadowRegion;
1447 return exposedRegion;
1453void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1457 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1458 int subW, subH, w, x, y, zeroX, zeroY;
1460 TQMemArray<TQRect>::Iterator it, itEnd;
1461 TQMemArray<TQRect> rectangles;
1464 int thickness, windowX, windowY, xOffset, yOffset;
1466 rectangles = exposed.rects();
1467 rootWindow = tqt_xrootwin();
1468 thickness = options->shadowThickness(isActive());
1469 windowX = this->x();
1470 windowY = this->y();
1471 xOffset = options->shadowXOffset(isActive());
1472 yOffset = options->shadowYOffset(isActive());
1473 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1476 itEnd = rectangles.end();
1477 for (it = rectangles.begin(); it != itEnd; ++it) {
1478 subW = (*it).width();
1479 subH = (*it).height();
1480 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1482 zeroX = (*it).x() - windowX + thickness - xOffset;
1483 zeroY = (*it).y() - windowY + thickness - yOffset;
1484 image = subPixmap.convertToImage();
1486 for (x = 0; x < subW; x++) {
1487 for (y = 0; y < subH; y++) {
1488 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1489 pixel = image.pixel(x, y);
1490 pixelRed = tqRed(pixel);
1491 pixelGreen = tqGreen(pixel);
1492 pixelBlue = tqBlue(pixel);
1493 image.setPixel(x, y,
1494 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1495 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1496 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1500 subPixmap.convertFromImage(image);
1501 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1508void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1509 TQRegion exposed,
int thickness,
double maxOpacity)
1511 int distance, intersectCount, i, j, x, y;
1513 double decay, factor, opacity;
1514 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1515 int lineIntersects, maxIntersects, maxY;
1516 int irBottom, irLeft, irRight, irTop, yIncrement;
1517 int subW, subH, w, h, zeroX, zeroY;
1519 TQMemArray<TQRect>::Iterator it, itEnd;
1520 TQMemArray<TQRect> rectangles;
1523 int windowX, windowY, xOffset, yOffset;
1525 rectangles = exposed.rects();
1526 rootWindow = tqt_xrootwin();
1527 windowX = this->x();
1528 windowY = this->y();
1529 xOffset = options->shadowXOffset(isActive());
1530 yOffset = options->shadowYOffset(isActive());
1531 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1532 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1533 lineIntersects = thickness * 2 + 1;
1534 factor = maxIntersects / maxOpacity;
1535 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1537 h = pixmap.height();
1538 xOffset = options->shadowXOffset(isActive());
1539 yOffset = options->shadowYOffset(isActive());
1541 opacityCache->resize(0);
1542 opacityCache->resize(w * h);
1543 occluded.translate(-windowX + thickness, -windowY + thickness);
1545 itEnd = rectangles.end();
1546 for (it = rectangles.begin(); it != itEnd; ++it) {
1547 subW = (*it).width();
1548 subH = (*it).height();
1549 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1552 zeroX = (*it).x() - windowX + thickness - xOffset;
1553 zeroY = (*it).y() - windowY + thickness - yOffset;
1554 image = subPixmap.convertToImage();
1560 for (x = 0; x < subW; x++) {
1561 irLeft = zeroX + x - thickness;
1562 irRight = zeroX + x + thickness;
1567 irTop = zeroY + y - thickness * yIncrement;
1570 irBottom = zeroY + y + thickness * yIncrement;
1572 if (opacity == -1) {
1577 for (j = irTop; j != irBottom; j += yIncrement) {
1580 for (i = irLeft; i <= irRight; i++) {
1581 if (occluded.contains(TQPoint(i, j)))
1587 if (intersectCount < 0)
1590 for (i = irLeft; i <= irRight; i++) {
1591 if (occluded.contains(TQPoint(i, irBottom)))
1596 distance = maxIntersects - intersectCount;
1597 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1599 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1600 pixel = image.pixel(x, y);
1601 pixelRed = tqRed(pixel);
1602 pixelGreen = tqGreen(pixel);
1603 pixelBlue = tqBlue(pixel);
1604 image.setPixel(x, y,
1605 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1606 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1607 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1609 for (i = irLeft; i <= irRight; i++) {
1610 if (occluded.contains(TQPoint(i, irTop)))
1618 irTop += yIncrement;
1619 for (j = irTop; j != irBottom; j += yIncrement) {
1620 if (occluded.contains(TQPoint(irLeft, j)))
1624 for (j = irTop; j != irBottom; j += yIncrement) {
1625 if (occluded.contains(TQPoint(irRight, j)))
1638 subPixmap.convertFromImage(image);
1639 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1647void Client::setMappingState(
int s)
1649 assert( client != None );
1650 assert( !deleting || s == WithdrawnState );
1651 if( mapping_state == s )
1653 bool was_unmanaged = ( mapping_state == WithdrawnState );
1655 if( mapping_state == WithdrawnState )
1657 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1660 assert( s == NormalState || s == IconicState );
1662 unsigned long data[2];
1663 data[0] = (
unsigned long) s;
1664 data[1] = (
unsigned long) None;
1665 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1666 PropModeReplace, (
unsigned char *)data, 2);
1669 postponeGeometryUpdates(
false );
1676void Client::rawShow()
1678 if( decoration != NULL )
1679 decoration->widget()->show();
1680 XMapWindow( tqt_xdisplay(), frame );
1683 XMapWindow( tqt_xdisplay(), wrapper );
1684 XMapWindow( tqt_xdisplay(), client );
1686 if (options->shadowEnabled(isActive()))
1687 drawDelayedShadow();
1695void Client::rawHide()
1704 drawIntersectingShadows();
1705 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1706 XUnmapWindow( tqt_xdisplay(), frame );
1707 XUnmapWindow( tqt_xdisplay(), wrapper );
1708 XUnmapWindow( tqt_xdisplay(), client );
1709 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1710 if( decoration != NULL )
1711 decoration->widget()->hide();
1712 workspace()->clientHidden(
this );
1715void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1720 memset(&ev, 0,
sizeof(ev));
1721 ev.xclient.type = ClientMessage;
1722 ev.xclient.window = w;
1723 ev.xclient.message_type = a;
1724 ev.xclient.format = 32;
1725 ev.xclient.data.l[0] = protocol;
1726 ev.xclient.data.l[1] = get_tqt_x_time();
1727 ev.xclient.data.l[2] = data1;
1728 ev.xclient.data.l[3] = data2;
1729 ev.xclient.data.l[4] = data3;
1731 if (w == tqt_xrootwin())
1732 mask = SubstructureRedirectMask;
1733 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1739bool Client::isCloseable()
const
1741 if( isModalSystemNotification())
1743 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1756 if ( Pdeletewindow )
1758 Notify::raise( Notify::Close );
1759 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1776 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1779 Notify::raise( Notify::Close );
1782 Notify::raise( Notify::TransDelete );
1783 if( isNormalWindow())
1784 Notify::raise( Notify::Delete );
1785 killProcess(
false );
1787 XKillClient(tqt_xdisplay(), window() );
1794void Client::pingWindow()
1798 if( options->killPingTimeout == 0 )
1800 if( ping_timer != NULL )
1802 ping_timer =
new TQTimer(
this );
1803 connect( ping_timer, TQ_SIGNAL( timeout()), TQ_SLOT( pingTimeout()));
1804 ping_timer->start( options->killPingTimeout,
true );
1805 ping_timestamp = get_tqt_x_time();
1806 workspace()->sendPingToWindow( window(), ping_timestamp );
1809void Client::gotPing( Time timestamp )
1812 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1816 if( process_killer != NULL )
1818 process_killer->kill();
1819 delete process_killer;
1820 process_killer = NULL;
1824void Client::pingTimeout()
1826 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1829 killProcess(
true, ping_timestamp );
1832void Client::killProcess(
bool ask, Time timestamp )
1834 if( process_killer != NULL )
1836 Q_ASSERT( !ask || timestamp != CurrentTime );
1838 pid_t pid = info->pid();
1839 if( pid <= 0 || machine.isEmpty())
1841 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1844 if( machine !=
"localhost" )
1847 proc <<
"xon" << machine <<
"kill" << pid;
1848 proc.start( TDEProcess::DontCare );
1851 ::kill( pid, SIGTERM );
1855 process_killer =
new TDEProcess(
this );
1856 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1857 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1858 <<
"--windowname" <<
caption().utf8()
1859 <<
"--applicationname" << resourceClass()
1860 <<
"--wid" << TQCString().setNum( window())
1861 <<
"--timestamp" << TQCString().setNum( timestamp );
1862 connect( process_killer, TQ_SIGNAL( processExited( TDEProcess* )),
1863 TQ_SLOT( processKillerExited()));
1864 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1866 delete process_killer;
1867 process_killer = NULL;
1873bool Client::isSuspendable()
const
1875 bool cansuspend =
true;
1876 if( skipTaskbar() || skipPager() )
1879 pid_t pid = info->pid();
1880 if( pid <= 0 || machine.isEmpty())
1882 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1883 if( machine !=
"localhost" )
1890 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1892 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1894 if (procStatFile.open(IO_ReadOnly))
1896 TQByteArray statRaw = procStatFile.readAll();
1897 procStatFile.close();
1899 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1900 char tbuf[PATH_MAX];
1902 TQString state(TQChar(inf->pr_sname));
1904 readlink(TQString(
"/proc/%1/path/a.out").arg(pid).latin1(),
1905 tbuf,
sizeof(tbuf));
1906 tcomm = basename(tbuf);
1908 TQString statString(statRaw);
1909 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1910 TQString tcomm = statFields[1];
1911 TQString state = statFields[2];
1916 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1918 Client* nextclient = *it;
1919 pid_t nextpid = nextclient->info->pid();
1920 TQCString nextmachine = nextclient->wmClientMachine(
true );
1921 if( nextpid > 0 && (!nextmachine.isEmpty()))
1923 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1925 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1931 TQString execname(tcomm);
1932 execname.truncate(execname.length()-1);
1933 execname = execname.remove(0,1);
1935 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1952bool Client::isResumeable()
const
1955 pid_t pid = info->pid();
1956 if( pid <= 0 || machine.isEmpty())
1958 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1959 if( machine !=
"localhost" )
1966 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1968 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1970 if (procStatFile.open(IO_ReadOnly))
1972 TQByteArray statRaw = procStatFile.readAll();
1973 procStatFile.close();
1975 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1976 TQString state(TQChar(inf->pr_sname));
1978 TQString statString(statRaw);
1979 TQStringList statFields = TQStringList::split(
" ", statString,
true);
1980 TQString tcomm = statFields[1];
1981 TQString state = statFields[2];
1999bool Client::queryUserSuspendedResume()
2003 if (process_resumer != NULL)
2008 process_resumer =
new TDEProcess(
this );
2009 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
2010 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
2011 <<
"--windowname" <<
caption().utf8()
2012 <<
"--applicationname" << resourceClass()
2013 <<
"--wid" << TQCString().setNum( window());
2014 connect( process_resumer, TQ_SIGNAL( processExited( TDEProcess* )),
2015 TQ_SLOT( processResumerExited()));
2016 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
2018 delete process_resumer;
2019 process_resumer = NULL;
2030void Client::suspendWindow()
2033 pid_t pid = info->pid();
2034 if( pid <= 0 || machine.isEmpty())
2036 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
2037 if( machine !=
"localhost" )
2043 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2045 Client* nextclient = *it;
2046 pid_t nextpid = nextclient->info->pid();
2047 TQCString nextmachine = nextclient->wmClientMachine(
true );
2048 if( nextpid > 0 && (!nextmachine.isEmpty()))
2050 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2052 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2053 nextclient->info->setVisibleName(newCaption.utf8());
2054 nextclient->info->setVisibleIconName(newCaption.utf8());
2055 nextclient->minimized_before_suspend = nextclient->isMinimized();
2056 nextclient->minimize(
true);
2060 ::kill( pid, SIGSTOP );
2064void Client::resumeWindow()
2067 pid_t pid = info->pid();
2068 if( pid <= 0 || machine.isEmpty())
2070 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2071 if( machine !=
"localhost" )
2077 ::kill( pid, SIGCONT );
2078 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2080 Client* nextclient = *it;
2081 pid_t nextpid = nextclient->info->pid();
2082 TQCString nextmachine = nextclient->wmClientMachine(
true );
2083 if( nextpid > 0 && (!nextmachine.isEmpty()))
2085 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2087 if (!nextclient->minimized_before_suspend)
2089 nextclient->unminimize(
true);
2091 nextclient->updateCaption();
2098void Client::processKillerExited()
2100 kdDebug( 1212 ) <<
"Killer exited" << endl;
2101 delete process_killer;
2102 process_killer = NULL;
2105void Client::processResumerExited()
2107 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2109 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2112 takeFocus( Allowed );
2114 delete process_resumer;
2115 process_resumer = NULL;
2118void Client::setSkipTaskbar(
bool b,
bool from_outside )
2120 int was_wants_tab_focus = wantsTabFocus();
2123 b = rules()->checkSkipTaskbar( b );
2124 original_skip_taskbar = b;
2126 if ( b == skipTaskbar() )
2129 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2130 updateWindowRules();
2131 if( was_wants_tab_focus != wantsTabFocus())
2132 workspace()->updateFocusChains(
this,
2133 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2136void Client::setSkipPager(
bool b )
2138 b = rules()->checkSkipPager( b );
2139 if ( b == skipPager() )
2142 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2143 updateWindowRules();
2146void Client::setModal(
bool m )
2157void Client::setDesktop(
int desktop )
2159 if(
desktop != NET::OnAllDesktops )
2160 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(),
desktop ));
2164 int was_desk = desk;
2167 if(( was_desk == NET::OnAllDesktops ) != (
desktop == NET::OnAllDesktops ))
2169 if ( isShown(
true ))
2170 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2171 workspace()->updateOnAllDesktopsOfTransients(
this );
2173 if( decoration != NULL )
2174 decoration->desktopChange();
2175 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2177 updateWindowRules();
2180void Client::setOnAllDesktops(
bool b )
2182 if(( b && isOnAllDesktops())
2183 || ( !b && !isOnAllDesktops()))
2186 setDesktop( NET::OnAllDesktops );
2188 setDesktop( workspace()->currentDesktop());
2191bool Client::isOnCurrentDesktop()
const
2193 return isOnDesktop( workspace()->currentDesktop());
2196int Client::screen()
const
2198 if( !options->xineramaEnabled )
2200 return workspace()->screenNumber( geometry().center());
2203bool Client::isOnScreen(
int screen )
const
2205 if( !options->xineramaEnabled )
2207 return workspace()->screenGeometry( screen ).intersects( geometry());
2211void Client::takeActivity(
int flags,
bool handled, allowed_t )
2213 if( !handled || !Ptakeactivity )
2215 if( flags & ActivityFocus )
2216 takeFocus( Allowed );
2217 if( flags & ActivityRaise )
2218 workspace()->raiseClient(
this );
2223 static Time previous_activity_timestamp;
2224 static Client* previous_client;
2225 if( previous_activity_timestamp == get_tqt_x_time() && previous_client !=
this )
2227 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2228 kdDebug( 1212 ) << kdBacktrace() << endl;
2230 previous_activity_timestamp = get_tqt_x_time();
2231 previous_client =
this;
2233 workspace()->sendTakeActivity(
this, get_tqt_x_time(), flags );
2237void Client::takeFocus( allowed_t )
2240 static Time previous_focus_timestamp;
2241 static Client* previous_client;
2242 if( previous_focus_timestamp == get_tqt_x_time() && previous_client !=
this )
2244 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2245 kdDebug( 1212 ) << kdBacktrace() << endl;
2247 previous_focus_timestamp = get_tqt_x_time();
2248 previous_client =
this;
2250 if ( rules()->checkAcceptFocus( input ))
2252 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, get_tqt_x_time() );
2256 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2258 workspace()->setShouldGetFocus(
this );
2270 if (isModalSystemNotification())
2272 return Pcontexthelp;
2286 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2287 TQWhatsThis::enterWhatsThisMode();
2296void Client::fetchName()
2298 setCaption( readName());
2301TQString Client::readName()
const
2303 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2304 return TQString::fromUtf8( info->name() );
2306 return KWin::readNameProperty( window(), XA_WM_NAME );
2309KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2311void Client::setCaption(
const TQString& s,
bool force )
2313 if ( s != cap_normal || force )
2315 bool reset_name = force;
2316 for(
unsigned int i = 0;
2319 if( !s[ i ].isPrint())
2322 bool was_suffix = ( !cap_suffix.isEmpty());
2323 TQString machine_suffix;
2326 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2327 cap_suffix = machine_suffix + shortcut_suffix;
2328 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2333 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2335 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2336 info->setVisibleName(
caption().utf8() );
2339 if(( (was_suffix && cap_suffix.isEmpty())
2342 info->setVisibleName(
"" );
2343 info->setVisibleIconName(
"" );
2345 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2346 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2348 if( isManaged() && decoration != NULL )
2349 decoration->captionChange();
2353void Client::updateCaption()
2355 setCaption( cap_normal,
true );
2358void Client::fetchIconicName()
2361 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2362 s = TQString::fromUtf8( info->iconName() );
2364 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2365 if ( s != cap_iconic )
2367 bool was_set = !cap_iconic.isEmpty();
2369 if( !cap_suffix.isEmpty())
2371 if( !cap_iconic.isEmpty())
2372 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2374 info->setVisibleIconName(
"" );
2383 return full ? cap_normal + cap_suffix : cap_normal;
2386void Client::getWMHints()
2388 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2390 window_group = None;
2394 if( hints->flags & InputHint )
2395 input = hints->input;
2396 if( hints->flags & WindowGroupHint )
2397 window_group = hints->window_group;
2398 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2399 XFree( (
char*)hints );
2403 updateAllowedActions();
2406void Client::getMotifHints()
2408 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2409 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2410 motif_noborder = mnoborder;
2411 if( !hasNETSupport())
2413 motif_may_resize = mresize;
2414 motif_may_move = mmove;
2417 motif_may_resize = motif_may_move =
true;
2420 motif_may_close = mclose;
2422 updateDecoration(
true );
2425void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2429 *icon = KWin::icon( win, 32, 32,
true, KWin::NETWM | KWin::WMHints );
2430 if( miniicon != NULL )
2432 if( icon == NULL || !icon->isNull())
2433 *miniicon = KWin::icon( win, 16, 16,
true, KWin::NETWM | KWin::WMHints );
2435 *miniicon = TQPixmap();
2439void Client::getIcons()
2442 readIcons( window(), &icon_pix, &miniicon_pix );
2443 if( icon_pix.isNull())
2445 icon_pix = group()->icon();
2446 miniicon_pix = group()->miniIcon();
2448 if( icon_pix.isNull() && isTransient())
2450 ClientList mainclients = mainClients();
2451 for( ClientList::ConstIterator it = mainclients.begin();
2452 it != mainclients.end() && icon_pix.isNull();
2455 icon_pix = (*it)->icon();
2456 miniicon_pix = (*it)->miniIcon();
2459 if( icon_pix.isNull())
2461 icon_pix = KWin::icon( window(), 32, 32,
true, KWin::ClassHint | KWin::XApp );
2462 miniicon_pix = KWin::icon( window(), 16, 16,
true, KWin::ClassHint | KWin::XApp );
2464 if( isManaged() && decoration != NULL )
2465 decoration->iconChange();
2468void Client::getWindowProtocols()
2479 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2481 for (i = 0; i < n; i++)
2482 if (p[i] == atoms->wm_delete_window)
2484 else if (p[i] == atoms->wm_take_focus)
2486 else if (p[i] == atoms->net_wm_take_activity)
2488 else if (p[i] == atoms->net_wm_context_help)
2490 else if (p[i] == atoms->net_wm_ping)
2497static int nullErrorHandler(Display *, XErrorEvent *)
2507 return getStringProperty(w, tqt_window_role).lower();
2515 return getStringProperty(w, tqt_sm_client_id);
2523 return getStringProperty(w, XA_WM_COMMAND,
' ');
2533 unsigned long nitems = 0;
2534 unsigned long extra = 0;
2535 unsigned char *data = 0;
2537 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2538 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2539 False, XA_WINDOW, &type, &format,
2540 &nitems, &extra, &data );
2541 XSetErrorHandler(oldHandler);
2542 if (status == Success )
2544 if (data && nitems > 0)
2545 result = *((Window*) data);
2552void Client::getWmClientLeader()
2564 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2576 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2581void Client::getWmClientMachine()
2583 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2584 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2585 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2586 if( client_machine.isEmpty())
2587 client_machine =
"localhost";
2596 TQCString result = client_machine;
2599 if( result !=
"localhost" && isLocalMachine( result ))
2600 result =
"localhost";
2611 if (wmClientLeaderWin)
2612 return wmClientLeaderWin;
2616bool Client::wantsTabFocus()
const
2618 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2622bool Client::wantsInput()
const
2624 return rules()->checkAcceptFocus( input || Ptakefocus );
2627bool Client::isDesktop()
const
2629 return windowType() == NET::Desktop;
2632bool Client::isDock()
const
2634 return windowType() == NET::Dock;
2637bool Client::isTopMenu()
const
2639 return windowType() == NET::TopMenu;
2643bool Client::isMenu()
const
2645 return windowType() == NET::Menu && !isTopMenu();
2648bool Client::isToolbar()
const
2650 return windowType() == NET::Toolbar;
2653bool Client::isSplash()
const
2655 return windowType() == NET::Splash;
2658bool Client::isUtility()
const
2660 return windowType() == NET::Utility;
2663bool Client::isDialog()
const
2665 return windowType() == NET::Dialog;
2668bool Client::isNormalWindow()
const
2670 return windowType() == NET::Normal;
2673bool Client::isSpecialWindow()
const
2675 return isDesktop() || isDock() || isSplash() || isTopMenu()
2679NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2681 NET::WindowType wt = info->windowType( supported_types );
2684 NET::WindowType wt2 = rules()->checkType( wt );
2688 info->setWindowType( wt );
2691 if( wt == NET::Menu )
2696 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2697 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2701 const char*
const oo_prefix =
"openoffice.org";
2703 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2705 if( wt == NET::Unknown )
2706 wt = isTransient() ? NET::Dialog : NET::Normal;
2714void Client::setCursor( Position m )
2722 case PositionTopLeft:
2723 case PositionBottomRight:
2724 setCursor( TQt::sizeFDiagCursor );
2726 case PositionBottomLeft:
2727 case PositionTopRight:
2728 setCursor( TQt::sizeBDiagCursor );
2731 case PositionBottom:
2732 setCursor( TQt::sizeVerCursor );
2736 setCursor( TQt::sizeHorCursor );
2740 setCursor( TQt::sizeAllCursor );
2742 setCursor( TQt::arrowCursor );
2749void Client::setCursor(
const TQCursor& c )
2751 if( c.handle() == cursor.handle())
2754 if( decoration != NULL )
2755 decoration->widget()->setCursor( cursor );
2756 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2759Client::Position Client::mousePosition(
const TQPoint& p )
const
2761 if( decoration != NULL )
2762 return decoration->mousePosition( p );
2763 return PositionCenter;
2766void Client::updateAllowedActions(
bool force )
2768 if( !isManaged() && !force )
2770 unsigned long old_allowed_actions = allowed_actions;
2771 allowed_actions = 0;
2773 allowed_actions |= NET::ActionMove;
2775 allowed_actions |= NET::ActionResize;
2777 allowed_actions |= NET::ActionMinimize;
2779 allowed_actions |= NET::ActionShade;
2781 if( isMaximizable())
2782 allowed_actions |= NET::ActionMax;
2783 if( userCanSetFullScreen())
2784 allowed_actions |= NET::ActionFullScreen;
2785 allowed_actions |= NET::ActionChangeDesktop;
2787 allowed_actions |= NET::ActionClose;
2788 if( old_allowed_actions == allowed_actions )
2791 info->setAllowedActions( allowed_actions );
2795void Client::autoRaise()
2797 workspace()->raiseClient(
this );
2801void Client::cancelAutoRaise()
2803 delete autoRaiseTimer;
2807void Client::setOpacity(uint opacity)
2812 if (opacity == Opacity::Opaque && !custom_opacity)
2814 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2815 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2818 if(opacity == opacity_)
2820 long data = opacity;
2821 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2822 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2827void Client::setShadowSize(uint shadowSize)
2831 long data = shadowSize;
2832 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2835uint Client::defaultOpacity()
2837 return defaultOpacity(isActive() || (
keepAbove() && options->keepAboveAsActive));
2840uint Client::defaultOpacity(
bool active)
2844 if( ruleOpacityActive() )
2845 return rule_opacity_active;
2847 return options->translucentActiveWindows ? options->activeWindowOpacity : Opacity::Opaque;
2851 if( ruleOpacityInactive() )
2852 return rule_opacity_inactive;
2854 return options->translucentInactiveWindows ? options->inactiveWindowOpacity : Opacity::Opaque;
2858void Client::updateOpacity()
2861 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2863 uint opacity = defaultOpacity();
2864 setOpacity(opacity);
2869 ClientList tmpGroupMembers = group()->members();
2870 ClientList groupMembers;
2871 groupMembers.append(
this);
2872 tmpGroupMembers.remove(
this);
2873 ClientList::Iterator it = tmpGroupMembers.begin();
2874 while (it != tmpGroupMembers.end())
2877 if ((*it) !=
this && (*it)->isBMP())
2881 if ((*it)->touches(
this))
2884 (*it)->setOpacity(opacity);
2886 (*it)->setShadowSize(options->activeWindowShadowSize);
2887 groupMembers.append(*it);
2888 tmpGroupMembers.remove(it);
2889 it = tmpGroupMembers.begin();
2895 for( ClientList::ConstIterator it2 = groupMembers.begin(); it2 != groupMembers.end(); it2++ )
2897 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2900 (*it)->setOpacity(opacity);
2901 (*it)->setShadowSize(isActive() ? options->activeWindowShadowSize : options->inactiveWindowShadowSize);
2902 groupMembers.append(*it);
2903 tmpGroupMembers.remove(it);
2904 it = tmpGroupMembers.begin();
2910 if (found)
continue;
2916 else if (isNormalWindow())
2919 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2920 if ((*it)->isUtility() || ((*it)->isDialog() && isActive() ))
2921 (*it)->setOpacity(opacity);
2925void Client::updateShadowSize()
2928 if (!(isNormalWindow() || isDialog() || isUtility() ))
2931 setShadowSize(options->activeWindowShadowSize);
2933 setShadowSize(options->inactiveWindowShadowSize);
2936uint Client::ruleOpacityInactive()
2938 return rule_opacity_inactive;
2941uint Client::ruleOpacityActive()
2943 return rule_opacity_active;
2946bool Client::getWindowOpacity()
2948 unsigned char *data = 0;
2951 unsigned long n, left;
2952 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
2953 if (result == Success && data && format == 32 )
2955 opacity_ = *
reinterpret_cast< long*
>( data );
2959 if ( !(Workspace::self()->initializing()
2960 && ( opacity_ == defaultOpacity(
false)
2961 || opacity_ == defaultOpacity(
true) ) ) )
2963 custom_opacity =
true;
2966 XFree ((
char*)data);
2972void Client::setCustomOpacityFlag(
bool custom)
2974 custom_opacity = custom;
2977uint Client::opacity()
2982int Client::opacityPercentage()
2984 return opacity_ / ( 0xffffffff / 100 );
2987bool Client::touches(
const Client* c)
2990 if (y() == c->y() + c->height())
2992 if (y() + height() == c->y())
2994 if (x() == c->x() + c->width())
2996 if (x() + width() == c->x())
3002kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
3005 return stream <<
"\'NULL_CLIENT\'";
3006 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
3008kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
3012 for( ClientList::ConstIterator it = list.begin();
3024kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3028 for( ConstClientList::ConstIterator it = list.begin();
3042TQPixmap * twin_get_menu_pix_hack()
3046 p = SmallIcon(
"bx2" );
3052#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)