16#include <tqapplication.h>
18#include <tqdatetime.h>
23#include <kstandarddirs.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 ),
123 demandAttentionKNotifyTimer( NULL ),
124 activeMaximizing(false),
131 shadowDelayTimer =
new TQTimer(
this);
132 opacityCache = &activeOpacityCache;
133 shadowAfterClient = NULL;
136 connect(shadowDelayTimer, TQT_SIGNAL(timeout()), TQT_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;
167 ignore_focus_stealing =
false;
168 demands_attention =
false;
169 check_active_modal =
false;
179 max_mode = MaximizeRestore;
180 maxmode_restore = MaximizeRestore;
184 frame_geometry = TQRect( 0, 0, 100, 100 );
185 client_size = TQSize( 100, 100 );
186 custom_opacity =
false;
187 rule_opacity_active = 0;
188 rule_opacity_inactive = 0;
198 assert(!moveResizeMode);
199 assert( client == None );
200 assert( frame == None && wrapper == None );
201 assert( decoration == NULL );
202 assert( postpone_geometry_updates == 0 );
203 assert( !check_active_modal );
209void Client::deleteClient( Client* c, allowed_t )
221 workspace()->discardUsedWindowRules(
this,
true );
222 StackingUpdatesBlocker blocker( workspace());
223 if (!custom_opacity) setOpacity(FALSE);
227 drawIntersectingShadows();
229 ++postpone_geometry_updates;
233 setMappingState( WithdrawnState );
237 workspace()->clientHidden(
this );
238 XUnmapWindow( tqt_xdisplay(), frameId());
243 workspace()->removeClient(
this, Allowed );
246 info->setDesktop( 0 );
248 info->setState( 0, info->state());
250 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
251 XDeleteProperty( tqt_xdisplay(), client, atoms->net_frame_extents );
252 XDeleteProperty( tqt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
253 XReparentWindow( tqt_xdisplay(), client, workspace()->rootWin(), x(), y());
254 XRemoveFromSaveSet( tqt_xdisplay(), client );
255 XSelectInput( tqt_xdisplay(), client, NoEventMask );
258 XMapWindow( tqt_xdisplay(), client );
265 XUnmapWindow( tqt_xdisplay(), client );
268 XDestroyWindow( tqt_xdisplay(), wrapper );
270 XDestroyWindow( tqt_xdisplay(), frame );
272 --postpone_geometry_updates;
273 checkNonExistentClients();
274 deleteClient(
this, Allowed );
280void Client::destroyClient()
284 workspace()->discardUsedWindowRules(
this,
true );
285 StackingUpdatesBlocker blocker( workspace());
289 drawIntersectingShadows();
291 ++postpone_geometry_updates;
294 workspace()->clientHidden(
this );
297 workspace()->removeClient(
this, Allowed );
299 XDestroyWindow( tqt_xdisplay(), wrapper );
301 XDestroyWindow( tqt_xdisplay(), frame );
303 --postpone_geometry_updates;
304 checkNonExistentClients();
305 deleteClient(
this, Allowed );
308void Client::updateDecoration(
bool check_workspace_pos,
bool force )
310 if( !force && (( decoration == NULL && noBorder())
311 || ( decoration != NULL && !noBorder())))
313 bool do_show =
false;
314 postponeGeometryUpdates(
true );
319 setMask( TQRegion());
320 decoration = workspace()->createDecoration( bridge );
323 decoration->widget()->installEventFilter(
this );
324 XReparentWindow( tqt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
325 decoration->widget()->lower();
326 decoration->borders( border_left, border_right, border_top, border_bottom );
327 options->onlyDecoTranslucent ?
328 setDecoHashProperty(border_top, border_right, border_bottom, border_left):
329 unsetDecoHashProperty();
330 int save_workarea_diff_x = workarea_diff_x;
331 int save_workarea_diff_y = workarea_diff_y;
332 move( calculateGravitation(
false ));
333 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
334 workarea_diff_x = save_workarea_diff_x;
335 workarea_diff_y = save_workarea_diff_y;
340 if( check_workspace_pos )
341 checkWorkspacePosition();
342 postponeGeometryUpdates(
false );
344 decoration->widget()->show();
345 updateFrameExtents();
346 updateOpacityCache();
349void Client::destroyDecoration()
351 if( decoration != NULL )
355 TQPoint grav = calculateGravitation(
true );
356 border_left = border_right = border_top = border_bottom = 0;
357 setMask( TQRegion());
358 int save_workarea_diff_x = workarea_diff_x;
359 int save_workarea_diff_y = workarea_diff_y;
360 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
362 workarea_diff_x = save_workarea_diff_x;
363 workarea_diff_y = save_workarea_diff_y;
367void Client::checkBorderSizes()
369 if( decoration == NULL )
371 int new_left, new_right, new_top, new_bottom;
372 decoration->borders( new_left, new_right, new_top, new_bottom );
373 if( new_left == border_left && new_right == border_right
374 && new_top == border_top && new_bottom == border_bottom )
376 GeometryUpdatesPostponer blocker(
this );
377 move( calculateGravitation(
true ));
378 border_left = new_left;
379 border_right = new_right;
380 border_top = new_top;
381 border_bottom = new_bottom;
382 if (border_left != new_left ||
383 border_right != new_right ||
384 border_top != new_top ||
385 border_bottom != new_bottom)
386 options->onlyDecoTranslucent ?
387 setDecoHashProperty(new_top, new_right, new_bottom, new_left):
388 unsetDecoHashProperty();
389 move( calculateGravitation(
false ));
390 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
391 checkWorkspacePosition();
394void Client::detectNoBorder()
396 if( Shape::hasShape( window()))
401 switch( windowType())
423 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
427void Client::detectShapable()
429 if( Shape::hasShape( window()))
431 switch( windowType())
451void Client::updateFrameExtents()
454 strut.left = border_left;
455 strut.right = border_right;
456 strut.top = border_top;
457 strut.bottom = border_bottom;
458 info->setFrameExtents( strut );
466void Client::resizeDecoration(
const TQSize& s )
468 if( decoration == NULL )
470 TQSize oldsize = decoration->widget()->size();
471 decoration->resize( s );
474 TQResizeEvent e( s, oldsize );
475 TQApplication::sendEvent( decoration->widget(), &e );
477 if (!moveResizeMode && options->shadowEnabled(isActive()))
481 updateOpacityCache();
485bool Client::noBorder()
const
487 return noborder || isFullScreen() || user_noborder || motif_noborder;
490bool Client::userCanSetNoBorder()
const
492 return !noborder && !isFullScreen() && !isShade();
495bool Client::isUserNoBorder()
const
497 return user_noborder;
500void Client::setUserNoBorder(
bool set )
502 if( !userCanSetNoBorder())
504 set = rules()->checkNoBorder( set );
505 if( user_noborder == set )
508 updateDecoration(
true,
false );
512bool Client::isModalSystemNotification()
const
514 unsigned char *data = 0;
517 unsigned long n, left;
518 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
519 if (result == Success && data && format == 32 )
526void Client::updateShape()
529 if( shape() && !noBorder())
532 updateDecoration(
true );
534 updateOpacityCache();
537 XShapeCombineShape(tqt_xdisplay(), frameId(), ShapeBounding,
538 clientPos().x(), clientPos().y(),
539 window(), ShapeBounding, ShapeSet);
545 if( Shape::version() >= 0x11 )
555 static Window helper_window = None;
556 if( helper_window == None )
557 helper_window = XCreateSimpleWindow( tqt_xdisplay(), tqt_xrootwin(),
558 0, 0, 1, 1, 0, 0, 0 );
559 XResizeWindow( tqt_xdisplay(), helper_window, width(), height());
560 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput, 0, 0,
561 frameId(), ShapeBounding, ShapeSet );
562 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
563 clientPos().x(), clientPos().y(),
564 window(), ShapeBounding, ShapeSubtract );
565 XShapeCombineShape( tqt_xdisplay(), helper_window, ShapeInput,
566 clientPos().x(), clientPos().y(),
567 window(), ShapeInput, ShapeUnion );
568 XShapeCombineShape( tqt_xdisplay(), frameId(), ShapeInput, 0, 0,
569 helper_window, ShapeInput, ShapeSet );
573void Client::setMask(
const TQRegion& reg,
int mode )
577 XShapeCombineMask( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
579 else if( mode == X::Unsorted )
580 XShapeCombineRegion( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
581 reg.handle(), ShapeSet );
584 TQMemArray< TQRect > rects = reg.rects();
585 XRectangle* xrects =
new XRectangle[ rects.count() ];
586 for(
unsigned int i = 0;
590 xrects[ i ].x = rects[ i ].x();
591 xrects[ i ].y = rects[ i ].y();
592 xrects[ i ].width = rects[ i ].width();
593 xrects[ i ].height = rects[ i ].height();
595 XShapeCombineRectangles( tqt_xdisplay(), frameId(), ShapeBounding, 0, 0,
596 xrects, rects.count(), ShapeSet, mode );
602TQRegion Client::mask()
const
605 return TQRegion( 0, 0, width(), height());
609void Client::setShapable(
bool b)
612 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
615void Client::hideClient(
bool hide )
628 if( isSpecialWindow())
630 if( isModalSystemNotification())
634 bool shown_mainwindow =
false;
635 ClientList mainclients = mainClients();
636 for( ClientList::ConstIterator it = mainclients.begin();
637 it != mainclients.end();
640 if( (*it)->isShown(
true ))
641 shown_mainwindow =
true;
643 if( !shown_mainwindow )
649 if( transientFor() != NULL )
651 if( !wantsTabFocus())
661 if( isModalSystemNotification())
675 info->setState(0, NET::Shaded);
677 Notify::raise( Notify::Minimize );
680 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
681 animateMinimizeOrUnminimize(
true );
686 updateAllowedActions();
687 workspace()->updateMinimizedOfTransients(
this );
689 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
692void Client::unminimize(
bool avoid_animation )
694 if (!queryUserSuspendedResume())
701 info->setState(NET::Shaded, NET::Shaded);
703 Notify::raise( Notify::UnMinimize );
705 if( isOnCurrentDesktop() && isShown(
true ))
707 if( mainClients().isEmpty() && !avoid_animation )
708 animateMinimizeOrUnminimize( FALSE );
711 updateAllowedActions();
712 workspace()->updateMinimizedOfTransients(
this );
716extern bool blockAnimation;
718void Client::animateMinimizeOrUnminimize(
bool minimize )
720 if ( blockAnimation )
722 if ( !options->animateMinimize )
725 if( decoration != NULL && decoration->animateMinimize(
minimize ))
732 float lf,rf,tf,bf,step;
734 int speed = options->animateMinimizeSpeed;
740 step = 40. * (11 - speed );
742 NETRect r = info->iconGeometry();
743 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
744 if ( !icongeom.isValid() )
747 TQPixmap pm = animationPixmap(
minimize ? width() : icongeom.width() );
749 TQRect before, after;
752 before = TQRect( x(), y(), width(), pm.height() );
753 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
757 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
758 after = TQRect( x(), y(), width(), pm.height() );
761 lf = (after.left() - before.left())/step;
762 rf = (after.right() - before.right())/step;
763 tf = (after.top() - before.top())/step;
764 bf = (after.bottom() - before.bottom())/step;
768 TQRect area = before;
776 TQPainter p ( workspace()->desktopWidget() );
777 bool need_to_clear = FALSE;
783 pm = animationPixmap( area.width() );
784 pm2 = TQPixmap::grabWindow( tqt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
785 p.drawPixmap( area.x(), area.y(), pm );
788 p.drawPixmap( area2.x(), area2.y(), pm3 );
789 need_to_clear = FALSE;
793 XFlush(tqt_xdisplay());
794 XSync( tqt_xdisplay(), FALSE );
798 area.setLeft(before.left() +
int(diff*lf));
799 area.setRight(before.right() +
int(diff*rf));
800 area.setTop(before.top() +
int(diff*tf));
801 area.setBottom(before.bottom() +
int(diff*bf));
804 if ( area2.intersects( area ) )
805 p.drawPixmap( area2.x(), area2.y(), pm2 );
809 need_to_clear = TRUE;
812 }
while ( t.elapsed() < step);
813 if (area2 == area || need_to_clear )
814 p.drawPixmap( area2.x(), area2.y(), pm2 );
824TQPixmap Client::animationPixmap(
int w )
826 TQFont font = options->font(isActive());
827 TQFontMetrics fm( font );
828 TQPixmap pm( w, fm.lineSpacing() );
829 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
831 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
832 p.setFont(options->font(isActive()));
833 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
838bool Client::isShadeable()
const
840 return !isSpecialWindow() && !noBorder();
843void Client::setShade( ShadeMode mode )
847 if( isModalSystemNotification())
849 mode = rules()->checkShade( mode );
850 if( shade_mode == mode )
852 bool was_shade = isShade();
853 ShadeMode was_shade_mode = shade_mode;
855 if( was_shade == isShade())
857 if( decoration != NULL )
858 decoration->shadeChange();
862 if( shade_mode == ShadeNormal )
864 if ( isShown(
true ) && isOnCurrentDesktop())
865 Notify::raise( Notify::ShadeUp );
867 else if( shade_mode == ShadeNone )
869 if( isShown(
true ) && isOnCurrentDesktop())
870 Notify::raise( Notify::ShadeDown );
873 assert( decoration != NULL );
874 GeometryUpdatesPostponer blocker(
this );
876 decoration->borders( border_left, border_right, border_top, border_bottom );
878 int as = options->animateShade? 10 : 1;
884 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
887 shade_geometry_change =
true;
888 TQSize s( sizeForClientSize( TQSize( clientSize())));
889 s.setHeight( border_top + border_bottom );
890 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
891 XUnmapWindow( tqt_xdisplay(), wrapper );
892 XUnmapWindow( tqt_xdisplay(), client );
893 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
899 int step = TQMAX( 4, QABS( h - s.height() ) / as )+1;
903 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
904 resizeDecoration( TQSize( s.width(), h ));
905 TQApplication::syncX();
906 }
while ( h > s.height() + step );
910 shade_geometry_change =
false;
913 if( was_shade_mode == ShadeHover )
914 workspace()->activateNextClient(
this );
916 workspace()->focusToNull();
920 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
925 shade_geometry_change =
true;
926 TQSize s( sizeForClientSize( clientSize()));
929 int step = TQMAX( 4, QABS( h - s.height() ) / as )+1;
933 XResizeWindow( tqt_xdisplay(), frameId(), s.width(), h );
934 resizeDecoration( TQSize( s.width(), h ));
938 TQApplication::syncX();
939 }
while ( h < s.height() - step );
942 shade_geometry_change =
false;
944 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
946 XMapWindow( tqt_xdisplay(), wrapperId());
947 XMapWindow( tqt_xdisplay(), window());
948 XDeleteProperty (tqt_xdisplay(), client, atoms->net_wm_window_shade);
949 if (options->shadowEnabled(
false))
951 for (ClientList::ConstIterator it = transients().begin();
952 it != transients().end(); ++it)
954 (*it)->removeShadow();
955 (*it)->drawDelayedShadow();
960 workspace()->requestFocus(
this );
962 checkMaximizeGeometry();
963 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
964 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
966 updateAllowedActions();
967 workspace()->updateMinimizedOfTransients(
this );
968 decoration->shadeChange();
972void Client::shadeHover()
974 setShade( ShadeHover );
978void Client::cancelShadeHover()
980 delete shadeHoverTimer;
984void Client::toggleShade()
987 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
990void Client::updateVisibility()
997 setMappingState( IconicState );
998 info->setState( NET::Hidden, NET::Hidden );
999 setSkipTaskbar(
true,
false );
1005 setSkipTaskbar( original_skip_taskbar,
false );
1009 setMappingState( IconicState );
1010 info->setState( NET::Hidden, NET::Hidden );
1015 info->setState( 0, NET::Hidden );
1016 if( !isOnCurrentDesktop())
1018 setMappingState( IconicState );
1024 bool belongs_to_desktop =
false;
1025 for( ClientList::ConstIterator it = group()->members().begin();
1026 it != group()->members().end();
1028 if( (*it)->isDesktop())
1030 belongs_to_desktop =
true;
1033 if( !belongs_to_desktop && workspace()->showingDesktop())
1034 workspace()->resetShowingDesktop(
true );
1036 setMappingState( IconicState );
1038 setMappingState( NormalState );
1043void Client::setShadowed(
bool shadowed)
1047 wasShadowed = isShadowed();
1048 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1058 if (!activeOpacityCache.isNull())
1059 activeOpacityCache.resize(0);
1060 if (!inactiveOpacityCache.isNull())
1061 inactiveOpacityCache.resize(0);
1066void Client::updateOpacityCache()
1068 if (!activeOpacityCache.isNull())
1069 activeOpacityCache.resize(0);
1070 if (!inactiveOpacityCache.isNull())
1071 inactiveOpacityCache.resize(0);
1073 if (!moveResizeMode) {
1077 drawIntersectingShadows();
1078 if (options->shadowEnabled(isActive()))
1079 drawDelayedShadow();
1087void Client::drawIntersectingShadows() {
1091 TQValueList<Client *> reshadowClients;
1092 TQValueListIterator<ShadowRegion> it;
1093 TQValueListIterator<Client *> it2;
1095 if (!options->shadowEnabled(
false))
1100 region = shapeBoundingRegion;
1105 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1106 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1107 !(*it).region.intersect(region).isEmpty())
1108 reshadowClients.append((*it).client);
1111 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1113 (*it2)->removeShadow();
1114 (*it2)->drawDelayedShadow();
1123void Client::drawOverlappingShadows(
bool waitForMe)
1127 TQValueList<Client *> reshadowClients;
1128 ClientList stacking_order;
1129 ClientList::ConstIterator it;
1130 TQValueListIterator<ShadowRegion> it2;
1131 TQValueListIterator<Client *> it3;
1133 if (!options->shadowEnabled(
false))
1138 region = shapeBoundingRegion;
1140 stacking_order = workspace()->stackingOrder();
1141 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1147 while (it != stacking_order.end()) {
1148 if ((*it)->windowType() == NET::Dock) {
1159 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1160 if ((*it2).client == (*it)) {
1161 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1162 && !(*it2).region.intersect(region).isEmpty())
1163 reshadowClients.append((*it2).client);
1170 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1171 (*it3)->removeShadow();
1172 if (it3 == reshadowClients.begin()) {
1174 (*it3)->drawShadowAfter(
this);
1176 (*it3)->drawDelayedShadow();
1182 (*it3)->drawShadowAfter(aClient);
1191void Client::drawDelayedShadow()
1193 shadowDelayTimer->stop();
1194 shadowDelayTimer->start(SHADOW_DELAY,
true);
1200void Client::drawShadowAfter(Client *after)
1202 shadowAfterClient = after;
1203 connect(after, TQT_SIGNAL(shadowDrawn()), TQT_SLOT(drawShadow()));
1209void Client::drawShadow()
1213 int i, count, ordering;
1216 if (shadowAfterClient != NULL) {
1217 disconnect(shadowAfterClient, TQT_SIGNAL(shadowDrawn()),
this, TQT_SLOT(drawShadow()));
1218 shadowAfterClient = NULL;
1221 if (!isOnCurrentDesktop())
1228 shapes = XShapeGetRectangles(tqt_xdisplay(), frameId(), ShapeBounding,
1232 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1234 shapeBoundingRegion = TQRegion();
1235 for (i = 0; i < count; i++) {
1237 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1239 shapeBoundingRegion += shapeRectangle;
1245 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1246 shapeBoundingRegion.translate(x(), y());
1249 if (!isShadowed() || hidden || isMinimized() ||
1250 maximizeMode() == MaximizeFull ||
1251 !options->shadowWindowType(windowType())) {
1263 TQMemArray<TQRgb> pixelData;
1264 TQPixmap shadowPixmap;
1266 TQRegion exposedRegion;
1267 ShadowRegion shadowRegion;
1268 int thickness, xOffset, yOffset;
1270 thickness = options->shadowThickness(isActive());
1271 xOffset = options->shadowXOffset(isActive());
1272 yOffset = options->shadowYOffset(isActive());
1273 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1275 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1276 width() + thickness * 2, height() + thickness * 2);
1277 shadowPixmap.resize(shadow.size());
1280 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1281 shadowWidget->setGeometry(shadow);
1282 XSelectInput(tqt_xdisplay(), shadowWidget->winId(),
1283 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1284 shadowWidget->installEventFilter(
this);
1288 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1289 shadow.y(), shadow.width(), shadow.height(), thickness,
1291 shadowRegion.region = exposedRegion;
1292 shadowRegion.client =
this;
1293 shadowRegions.append(shadowRegion);
1295 if (opacityCache->isNull())
1296 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1297 exposedRegion, thickness,
1298 options->shadowOpacity(isActive()));
1300 imposeCachedShadow(shadowPixmap, exposedRegion);
1303 TQMemArray<TQRect> exposedRects;
1304 TQMemArray<TQRect>::Iterator it, itEnd;
1305 XRectangle *shadowShapes;
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);
1315 exposedRects = exposedRegion.rects();
1317 itEnd = exposedRects.end();
1318 shadowShapes =
new XRectangle[exposedRects.count()];
1319 for (it = exposedRects.begin(); it != itEnd; ++it) {
1320 shadowShapes[i].x = (*it).x();
1321 shadowShapes[i].y = (*it).y();
1322 shadowShapes[i].width = (*it).width();
1323 shadowShapes[i].height = (*it).height();
1326 XShapeCombineRectangles(tqt_xdisplay(), shadowWidget->winId(),
1327 ShapeBounding, -x() + thickness - xOffset,
1328 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1330 delete [] shadowShapes;
1332 if (opacityCache->isNull())
1333 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1334 exposedRegion, thickness,
1335 options->shadowOpacity(isActive()));
1337 imposeCachedShadow(shadowPixmap, exposedRegion);
1344 shadowWidget->setErasePixmap(shadowPixmap);
1349 ClientList stacking_order = workspace()->stackingOrder();
1350 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1351 if ((*it)->isDesktop())
1354 shadows[0] = (*it)->frameId();
1355 shadows[1] = shadowWidget->winId();
1359 shadows[0] = frameId();
1360 if (shadowWidget != NULL)
1361 shadows[1] = shadowWidget->winId();
1364 XRestackWindows(tqt_xdisplay(), shadows, 2);
1368 XMapWindow(tqt_xdisplay(), shadowWidget->winId());
1377void Client::removeShadow()
1379 TQValueList<ShadowRegion>::Iterator it;
1381 shadowDelayTimer->stop();
1383 if (shadowWidget != NULL) {
1384 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1385 if ((*it).client ==
this) {
1386 shadowRegions.remove(it);
1389 delete shadowWidget;
1390 shadowWidget = NULL;
1398TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1399 int h,
int thickness,
int xOffset,
int yOffset)
1401 TQRegion exposedRegion;
1403 exposedRegion = TQRegion(x, y, w, h);
1404 exposedRegion -= occludedRegion;
1406 if (thickness > 0) {
1409 TQMemArray<TQRect> occludedRects;
1410 TQMemArray<TQRect>::Iterator it, itEnd;
1411 TQRegion shadowRegion;
1413 occludedRects = occludedRegion.rects();
1414 itEnd = occludedRects.end();
1415 for (it = occludedRects.begin(); it != itEnd; ++it) {
1419 it->setTop(it->top() - thickness + yOffset);
1420 it->setLeft(it->left() - thickness + xOffset);
1421 it->setRight(it->right() + thickness + xOffset);
1422 it->setBottom(it->bottom() + thickness + yOffset);
1423 shadowRegion += TQRegion(*it);
1425 exposedRegion -= exposedRegion - shadowRegion;
1428 return exposedRegion;
1434void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1438 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1439 int subW, subH, w, x, y, zeroX, zeroY;
1441 TQMemArray<TQRect>::Iterator it, itEnd;
1442 TQMemArray<TQRect> rectangles;
1445 int thickness, windowX, windowY, xOffset, yOffset;
1447 rectangles = exposed.rects();
1448 rootWindow = tqt_xrootwin();
1449 thickness = options->shadowThickness(isActive());
1450 windowX = this->x();
1451 windowY = this->y();
1452 xOffset = options->shadowXOffset(isActive());
1453 yOffset = options->shadowYOffset(isActive());
1454 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1457 itEnd = rectangles.end();
1458 for (it = rectangles.begin(); it != itEnd; ++it) {
1459 subW = (*it).width();
1460 subH = (*it).height();
1461 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1463 zeroX = (*it).x() - windowX + thickness - xOffset;
1464 zeroY = (*it).y() - windowY + thickness - yOffset;
1465 image = subPixmap.convertToImage();
1467 for (x = 0; x < subW; x++) {
1468 for (y = 0; y < subH; y++) {
1469 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1470 pixel = image.pixel(x, y);
1471 pixelRed = tqRed(pixel);
1472 pixelGreen = tqGreen(pixel);
1473 pixelBlue = tqBlue(pixel);
1474 image.setPixel(x, y,
1475 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1476 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1477 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1481 subPixmap.convertFromImage(image);
1482 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1489void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1490 TQRegion exposed,
int thickness,
double maxOpacity)
1492 int distance, intersectCount, i, j, x, y;
1494 double decay, factor, opacity;
1495 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1496 int lineIntersects, maxIntersects, maxY;
1497 int irBottom, irLeft, irRight, irTop, yIncrement;
1498 int subW, subH, w, h, zeroX, zeroY;
1500 TQMemArray<TQRect>::Iterator it, itEnd;
1501 TQMemArray<TQRect> rectangles;
1504 int windowX, windowY, xOffset, yOffset;
1506 rectangles = exposed.rects();
1507 rootWindow = tqt_xrootwin();
1508 windowX = this->x();
1509 windowY = this->y();
1510 xOffset = options->shadowXOffset(isActive());
1511 yOffset = options->shadowYOffset(isActive());
1512 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1513 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1514 lineIntersects = thickness * 2 + 1;
1515 factor = maxIntersects / maxOpacity;
1516 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1518 h = pixmap.height();
1519 xOffset = options->shadowXOffset(isActive());
1520 yOffset = options->shadowYOffset(isActive());
1522 opacityCache->resize(0);
1523 opacityCache->resize(w * h);
1524 occluded.translate(-windowX + thickness, -windowY + thickness);
1526 itEnd = rectangles.end();
1527 for (it = rectangles.begin(); it != itEnd; ++it) {
1528 subW = (*it).width();
1529 subH = (*it).height();
1530 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1533 zeroX = (*it).x() - windowX + thickness - xOffset;
1534 zeroY = (*it).y() - windowY + thickness - yOffset;
1535 image = subPixmap.convertToImage();
1541 for (x = 0; x < subW; x++) {
1542 irLeft = zeroX + x - thickness;
1543 irRight = zeroX + x + thickness;
1548 irTop = zeroY + y - thickness * yIncrement;
1551 irBottom = zeroY + y + thickness * yIncrement;
1553 if (opacity == -1) {
1558 for (j = irTop; j != irBottom; j += yIncrement) {
1561 for (i = irLeft; i <= irRight; i++) {
1562 if (occluded.contains(TQPoint(i, j)))
1568 if (intersectCount < 0)
1571 for (i = irLeft; i <= irRight; i++) {
1572 if (occluded.contains(TQPoint(i, irBottom)))
1577 distance = maxIntersects - intersectCount;
1578 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1580 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1581 pixel = image.pixel(x, y);
1582 pixelRed = tqRed(pixel);
1583 pixelGreen = tqGreen(pixel);
1584 pixelBlue = tqBlue(pixel);
1585 image.setPixel(x, y,
1586 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1587 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1588 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1590 for (i = irLeft; i <= irRight; i++) {
1591 if (occluded.contains(TQPoint(i, irTop)))
1599 irTop += yIncrement;
1600 for (j = irTop; j != irBottom; j += yIncrement) {
1601 if (occluded.contains(TQPoint(irLeft, j)))
1605 for (j = irTop; j != irBottom; j += yIncrement) {
1606 if (occluded.contains(TQPoint(irRight, j)))
1619 subPixmap.convertFromImage(image);
1620 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1628void Client::setMappingState(
int s)
1630 assert( client != None );
1631 assert( !deleting || s == WithdrawnState );
1632 if( mapping_state == s )
1634 bool was_unmanaged = ( mapping_state == WithdrawnState );
1636 if( mapping_state == WithdrawnState )
1638 XDeleteProperty( tqt_xdisplay(), window(), tqt_wm_state );
1641 assert( s == NormalState || s == IconicState );
1643 unsigned long data[2];
1644 data[0] = (
unsigned long) s;
1645 data[1] = (
unsigned long) None;
1646 XChangeProperty(tqt_xdisplay(), window(), tqt_wm_state, tqt_wm_state, 32,
1647 PropModeReplace, (
unsigned char *)data, 2);
1650 postponeGeometryUpdates(
false );
1657void Client::rawShow()
1659 if( decoration != NULL )
1660 decoration->widget()->show();
1661 XMapWindow( tqt_xdisplay(), frame );
1664 XMapWindow( tqt_xdisplay(), wrapper );
1665 XMapWindow( tqt_xdisplay(), client );
1667 if (options->shadowEnabled(isActive()))
1668 drawDelayedShadow();
1676void Client::rawHide()
1685 drawIntersectingShadows();
1686 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask );
1687 XUnmapWindow( tqt_xdisplay(), frame );
1688 XUnmapWindow( tqt_xdisplay(), wrapper );
1689 XUnmapWindow( tqt_xdisplay(), client );
1690 XSelectInput( tqt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1691 if( decoration != NULL )
1692 decoration->widget()->hide();
1693 workspace()->clientHidden(
this );
1696void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1701 memset(&ev, 0,
sizeof(ev));
1702 ev.xclient.type = ClientMessage;
1703 ev.xclient.window = w;
1704 ev.xclient.message_type = a;
1705 ev.xclient.format = 32;
1706 ev.xclient.data.l[0] = protocol;
1707 ev.xclient.data.l[1] = GET_QT_X_TIME();
1708 ev.xclient.data.l[2] = data1;
1709 ev.xclient.data.l[3] = data2;
1710 ev.xclient.data.l[4] = data3;
1712 if (w == tqt_xrootwin())
1713 mask = SubstructureRedirectMask;
1714 XSendEvent(tqt_xdisplay(), w, False, mask, &ev);
1720bool Client::isCloseable()
const
1722 if( isModalSystemNotification())
1724 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1737 if ( Pdeletewindow )
1739 Notify::raise( Notify::Close );
1740 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1757 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1760 Notify::raise( Notify::Close );
1763 Notify::raise( Notify::TransDelete );
1764 if( isNormalWindow())
1765 Notify::raise( Notify::Delete );
1766 killProcess(
false );
1768 XKillClient(tqt_xdisplay(), window() );
1775void Client::pingWindow()
1779 if( options->killPingTimeout == 0 )
1781 if( ping_timer != NULL )
1783 ping_timer =
new TQTimer(
this );
1784 connect( ping_timer, TQT_SIGNAL( timeout()), TQT_SLOT( pingTimeout()));
1785 ping_timer->start( options->killPingTimeout,
true );
1786 ping_timestamp = GET_QT_X_TIME();
1787 workspace()->sendPingToWindow( window(), ping_timestamp );
1790void Client::gotPing( Time timestamp )
1793 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1797 if( process_killer != NULL )
1799 process_killer->kill();
1800 delete process_killer;
1801 process_killer = NULL;
1805void Client::pingTimeout()
1807 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1810 killProcess(
true, ping_timestamp );
1813void Client::killProcess(
bool ask, Time timestamp )
1815 if( process_killer != NULL )
1817 Q_ASSERT( !ask || timestamp != CurrentTime );
1819 pid_t pid = info->pid();
1820 if( pid <= 0 || machine.isEmpty())
1822 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1825 if( machine !=
"localhost" )
1828 proc <<
"xon" << machine <<
"kill" << pid;
1829 proc.start( TDEProcess::DontCare );
1832 ::kill( pid, SIGTERM );
1836 process_killer =
new TDEProcess(
this );
1837 *process_killer << TDEStandardDirs::findExe(
"twin_killer_helper" )
1838 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1839 <<
"--windowname" <<
caption().utf8()
1840 <<
"--applicationname" << resourceClass()
1841 <<
"--wid" << TQCString().setNum( window())
1842 <<
"--timestamp" << TQCString().setNum( timestamp );
1843 connect( process_killer, TQT_SIGNAL( processExited( TDEProcess* )),
1844 TQT_SLOT( processKillerExited()));
1845 if( !process_killer->start( TDEProcess::NotifyOnExit ))
1847 delete process_killer;
1848 process_killer = NULL;
1854bool Client::isSuspendable()
const
1856 bool cansuspend =
true;
1857 if( skipTaskbar() || skipPager() )
1860 pid_t pid = info->pid();
1861 if( pid <= 0 || machine.isEmpty())
1863 kdDebug( 1212 ) <<
"Check suspendable process:" << pid <<
"(" << machine <<
")" << endl;
1864 if( machine !=
"localhost" )
1871 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1873 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1875 if (procStatFile.open(IO_ReadOnly))
1877 TQByteArray statRaw = procStatFile.readAll();
1878 procStatFile.close();
1880 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1881 char tbuf[PATH_MAX];
1883 TQString state(TQChar(inf->pr_sname));
1885 readlink(TQString(
"/proc/%1/path/a.out").arg(pid).latin1(),
1886 tbuf,
sizeof(tbuf));
1887 tcomm = basename(tbuf);
1889 TQString statString(statRaw);
1890 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1891 TQString tcomm = statFields[1];
1892 TQString state = statFields[2];
1897 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
1899 Client* nextclient = *it;
1900 pid_t nextpid = nextclient->info->pid();
1901 TQCString nextmachine = nextclient->wmClientMachine(
true );
1902 if( nextpid > 0 && (!nextmachine.isEmpty()))
1904 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
1906 if( nextclient->skipTaskbar() || nextclient->skipPager() )
1912 TQString execname(tcomm);
1913 execname.truncate(execname.length()-1);
1914 execname = execname.remove(0,1);
1916 if( (execname ==
"kdesktop") || (execname ==
"kicker") )
1933bool Client::isResumeable()
const
1936 pid_t pid = info->pid();
1937 if( pid <= 0 || machine.isEmpty())
1939 kdDebug( 1212 ) <<
"Check resumeable process:" << pid <<
"(" << machine <<
")" << endl;
1940 if( machine !=
"localhost" )
1947 TQFile procStatFile(TQString(
"/proc/%1/lwp/1/lwpsinfo").arg(pid));
1949 TQFile procStatFile(TQString(
"/proc/%1/stat").arg(pid));
1951 if (procStatFile.open(IO_ReadOnly))
1953 TQByteArray statRaw = procStatFile.readAll();
1954 procStatFile.close();
1956 lwpsinfo_t *inf = (lwpsinfo_t *)statRaw.data();
1957 TQString state(TQChar(inf->pr_sname));
1959 TQString statString(statRaw);
1960 TQStringList statFields = TQStringList::split(
" ", statString, TRUE);
1961 TQString tcomm = statFields[1];
1962 TQString state = statFields[2];
1980bool Client::queryUserSuspendedResume()
1984 if (process_resumer != NULL)
1989 process_resumer =
new TDEProcess(
this );
1990 *process_resumer << TDEStandardDirs::findExe(
"twin_resumer_helper" )
1991 <<
"--pid" << TQCString().setNum( info->pid() ) <<
"--hostname" <<
wmClientMachine(
true )
1992 <<
"--windowname" <<
caption().utf8()
1993 <<
"--applicationname" << resourceClass()
1994 <<
"--wid" << TQCString().setNum( window());
1995 connect( process_resumer, TQT_SIGNAL( processExited( TDEProcess* )),
1996 TQT_SLOT( processResumerExited()));
1997 if( !process_resumer->start( TDEProcess::NotifyOnExit ))
1999 delete process_resumer;
2000 process_resumer = NULL;
2011void Client::suspendWindow()
2014 pid_t pid = info->pid();
2015 if( pid <= 0 || machine.isEmpty())
2017 kdDebug( 1212 ) <<
"Suspend process:" << pid <<
"(" << machine <<
")" << endl;
2018 if( machine !=
"localhost" )
2024 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2026 Client* nextclient = *it;
2027 pid_t nextpid = nextclient->info->pid();
2028 TQCString nextmachine = nextclient->wmClientMachine(
true );
2029 if( nextpid > 0 && (!nextmachine.isEmpty()))
2031 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2033 TQString newCaption = TQString(readName()).append(
" <").append(i18n(
"Suspended")).append(
">");
2034 nextclient->info->setVisibleName(newCaption.utf8());
2035 nextclient->info->setVisibleIconName(newCaption.utf8());
2036 nextclient->minimized_before_suspend = nextclient->isMinimized();
2037 nextclient->minimize(
true);
2041 ::kill( pid, SIGSTOP );
2045void Client::resumeWindow()
2048 pid_t pid = info->pid();
2049 if( pid <= 0 || machine.isEmpty())
2051 kdDebug( 1212 ) <<
"Resume process:" << pid <<
"(" << machine <<
")" << endl;
2052 if( machine !=
"localhost" )
2058 ::kill( pid, SIGCONT );
2059 for ( ClientList::ConstIterator it = workspace()->clients.begin(); it != workspace()->clients.end(); ++it)
2061 Client* nextclient = *it;
2062 pid_t nextpid = nextclient->info->pid();
2063 TQCString nextmachine = nextclient->wmClientMachine(
true );
2064 if( nextpid > 0 && (!nextmachine.isEmpty()))
2066 if( ( nextmachine ==
"localhost" ) && ( pid == nextpid ) )
2068 if (!nextclient->minimized_before_suspend)
2070 nextclient->unminimize(
true);
2072 nextclient->updateCaption();
2079void Client::processKillerExited()
2081 kdDebug( 1212 ) <<
"Killer exited" << endl;
2082 delete process_killer;
2083 process_killer = NULL;
2086void Client::processResumerExited()
2088 kdDebug( 1212 ) <<
"Resumer exited" << endl;
2090 if ((process_resumer->exitStatus() == 0) || (process_resumer->exitStatus() == 2))
2093 takeFocus( Allowed );
2095 delete process_resumer;
2096 process_resumer = NULL;
2099void Client::setSkipTaskbar(
bool b,
bool from_outside )
2101 int was_wants_tab_focus = wantsTabFocus();
2104 b = rules()->checkSkipTaskbar( b );
2105 original_skip_taskbar = b;
2107 if ( b == skipTaskbar() )
2110 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
2111 updateWindowRules();
2112 if( was_wants_tab_focus != wantsTabFocus())
2113 workspace()->updateFocusChains(
this,
2114 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
2117void Client::setSkipPager(
bool b )
2119 b = rules()->checkSkipPager( b );
2120 if ( b == skipPager() )
2123 info->setState( b?NET::SkipPager:0, NET::SkipPager );
2124 updateWindowRules();
2127void Client::setModal(
bool m )
2138void Client::setDesktop(
int desktop )
2140 if(
desktop != NET::OnAllDesktops )
2141 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(),
desktop ));
2145 int was_desk = desk;
2148 if(( was_desk == NET::OnAllDesktops ) != (
desktop == NET::OnAllDesktops ))
2150 if ( isShown(
true ))
2151 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
2152 workspace()->updateOnAllDesktopsOfTransients(
this );
2154 if( decoration != NULL )
2155 decoration->desktopChange();
2156 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
2158 updateWindowRules();
2161void Client::setOnAllDesktops(
bool b )
2163 if(( b && isOnAllDesktops())
2164 || ( !b && !isOnAllDesktops()))
2167 setDesktop( NET::OnAllDesktops );
2169 setDesktop( workspace()->currentDesktop());
2172bool Client::isOnCurrentDesktop()
const
2174 return isOnDesktop( workspace()->currentDesktop());
2177int Client::screen()
const
2179 if( !options->xineramaEnabled )
2181 return workspace()->screenNumber( geometry().center());
2184bool Client::isOnScreen(
int screen )
const
2186 if( !options->xineramaEnabled )
2188 return workspace()->screenGeometry( screen ).intersects( geometry());
2192void Client::takeActivity(
int flags,
bool handled, allowed_t )
2194 if( !handled || !Ptakeactivity )
2196 if( flags & ActivityFocus )
2197 takeFocus( Allowed );
2198 if( flags & ActivityRaise )
2199 workspace()->raiseClient(
this );
2204 static Time previous_activity_timestamp;
2205 static Client* previous_client;
2206 if( previous_activity_timestamp == GET_QT_X_TIME() && previous_client !=
this )
2208 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
2209 kdDebug( 1212 ) << kdBacktrace() << endl;
2211 previous_activity_timestamp = GET_QT_X_TIME();
2212 previous_client =
this;
2214 workspace()->sendTakeActivity(
this, GET_QT_X_TIME(), flags );
2218void Client::takeFocus( allowed_t )
2221 static Time previous_focus_timestamp;
2222 static Client* previous_client;
2223 if( previous_focus_timestamp == GET_QT_X_TIME() && previous_client !=
this )
2225 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
2226 kdDebug( 1212 ) << kdBacktrace() << endl;
2228 previous_focus_timestamp = GET_QT_X_TIME();
2229 previous_client =
this;
2231 if ( rules()->checkAcceptFocus( input ))
2233 XSetInputFocus( tqt_xdisplay(), window(), RevertToPointerRoot, GET_QT_X_TIME() );
2235 bool activePrev = active;
2238 active = activePrev;
2242 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
2244 workspace()->setShouldGetFocus(
this );
2256 if (isModalSystemNotification())
2258 return Pcontexthelp;
2272 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2273 TQWhatsThis::enterWhatsThisMode();
2282void Client::fetchName()
2284 setCaption( readName());
2287TQString Client::readName()
const
2289 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2290 return TQString::fromUtf8( info->name() );
2292 return KWin::readNameProperty( window(), XA_WM_NAME );
2295KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2297void Client::setCaption(
const TQString& s,
bool force )
2299 if ( s != cap_normal || force )
2301 bool reset_name = force;
2302 for(
unsigned int i = 0;
2305 if( !s[ i ].isPrint())
2308 bool was_suffix = ( !cap_suffix.isEmpty());
2309 TQString machine_suffix;
2312 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2313 cap_suffix = machine_suffix + shortcut_suffix;
2314 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2319 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2321 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2322 info->setVisibleName(
caption().utf8() );
2325 if(( (was_suffix && cap_suffix.isEmpty())
2328 info->setVisibleName(
"" );
2329 info->setVisibleIconName(
"" );
2331 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2332 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2334 if( isManaged() && decoration != NULL )
2335 decoration->captionChange();
2339void Client::updateCaption()
2341 setCaption( cap_normal,
true );
2344void Client::fetchIconicName()
2347 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2348 s = TQString::fromUtf8( info->iconName() );
2350 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2351 if ( s != cap_iconic )
2353 bool was_set = !cap_iconic.isEmpty();
2355 if( !cap_suffix.isEmpty())
2357 if( !cap_iconic.isEmpty())
2358 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2360 info->setVisibleIconName(
"" );
2369 return full ? cap_normal + cap_suffix : cap_normal;
2372void Client::getWMHints()
2374 XWMHints *hints = XGetWMHints(tqt_xdisplay(), window() );
2376 window_group = None;
2380 if( hints->flags & InputHint )
2381 input = hints->input;
2382 if( hints->flags & WindowGroupHint )
2383 window_group = hints->window_group;
2384 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2385 XFree( (
char*)hints );
2389 updateAllowedActions();
2392void Client::getMotifHints()
2394 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2395 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2396 motif_noborder = mnoborder;
2397 if( !hasNETSupport())
2399 motif_may_resize = mresize;
2400 motif_may_move = mmove;
2403 motif_may_resize = motif_may_move =
true;
2406 motif_may_close = mclose;
2408 updateDecoration(
true );
2411void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2415 *icon = KWin::icon( win, 32, 32, TRUE, KWin::NETWM | KWin::WMHints );
2416 if( miniicon != NULL )
2418 if( icon == NULL || !icon->isNull())
2419 *miniicon = KWin::icon( win, 16, 16, TRUE, KWin::NETWM | KWin::WMHints );
2421 *miniicon = TQPixmap();
2425void Client::getIcons()
2428 readIcons( window(), &icon_pix, &miniicon_pix );
2429 if( icon_pix.isNull())
2431 icon_pix = group()->icon();
2432 miniicon_pix = group()->miniIcon();
2434 if( icon_pix.isNull() && isTransient())
2436 ClientList mainclients = mainClients();
2437 for( ClientList::ConstIterator it = mainclients.begin();
2438 it != mainclients.end() && icon_pix.isNull();
2441 icon_pix = (*it)->icon();
2442 miniicon_pix = (*it)->miniIcon();
2445 if( icon_pix.isNull())
2447 icon_pix = KWin::icon( window(), 32, 32, TRUE, KWin::ClassHint | KWin::XApp );
2448 miniicon_pix = KWin::icon( window(), 16, 16, TRUE, KWin::ClassHint | KWin::XApp );
2450 if( isManaged() && decoration != NULL )
2451 decoration->iconChange();
2454void Client::getWindowProtocols()
2465 if (XGetWMProtocols(tqt_xdisplay(), window(), &p, &n))
2467 for (i = 0; i < n; i++)
2468 if (p[i] == atoms->wm_delete_window)
2470 else if (p[i] == atoms->wm_take_focus)
2472 else if (p[i] == atoms->net_wm_take_activity)
2474 else if (p[i] == atoms->net_wm_context_help)
2476 else if (p[i] == atoms->net_wm_ping)
2483static int nullErrorHandler(Display *, XErrorEvent *)
2493 return getStringProperty(w, tqt_window_role).lower();
2501 return getStringProperty(w, tqt_sm_client_id);
2509 return getStringProperty(w, XA_WM_COMMAND,
' ');
2519 unsigned long nitems = 0;
2520 unsigned long extra = 0;
2521 unsigned char *data = 0;
2523 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2524 status = XGetWindowProperty( tqt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2525 FALSE, XA_WINDOW, &type, &format,
2526 &nitems, &extra, &data );
2527 XSetErrorHandler(oldHandler);
2528 if (status == Success )
2530 if (data && nitems > 0)
2531 result = *((Window*) data);
2538void Client::getWmClientLeader()
2550 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2562 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2567void Client::getWmClientMachine()
2569 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2570 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2571 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2572 if( client_machine.isEmpty())
2573 client_machine =
"localhost";
2582 TQCString result = client_machine;
2585 if( result !=
"localhost" && isLocalMachine( result ))
2586 result =
"localhost";
2597 if (wmClientLeaderWin)
2598 return wmClientLeaderWin;
2602bool Client::wantsTabFocus()
const
2604 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2608bool Client::wantsInput()
const
2610 return rules()->checkAcceptFocus( input || Ptakefocus );
2613bool Client::isDesktop()
const
2615 return windowType() == NET::Desktop;
2618bool Client::isDock()
const
2620 return windowType() == NET::Dock;
2623bool Client::isTopMenu()
const
2625 return windowType() == NET::TopMenu;
2629bool Client::isMenu()
const
2631 return windowType() == NET::Menu && !isTopMenu();
2634bool Client::isToolbar()
const
2636 return windowType() == NET::Toolbar;
2639bool Client::isSplash()
const
2641 return windowType() == NET::Splash;
2644bool Client::isUtility()
const
2646 return windowType() == NET::Utility;
2649bool Client::isDialog()
const
2651 return windowType() == NET::Dialog;
2654bool Client::isNormalWindow()
const
2656 return windowType() == NET::Normal;
2659bool Client::isSpecialWindow()
const
2661 return isDesktop() || isDock() || isSplash() || isTopMenu()
2665NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2667 NET::WindowType wt = info->windowType( supported_types );
2670 NET::WindowType wt2 = rules()->checkType( wt );
2674 info->setWindowType( wt );
2677 if( wt == NET::Menu )
2682 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2683 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2687 const char*
const oo_prefix =
"openoffice.org";
2689 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2691 if( wt == NET::Unknown )
2692 wt = isTransient() ? NET::Dialog : NET::Normal;
2700void Client::setCursor( Position m )
2708 case PositionTopLeft:
2709 case PositionBottomRight:
2710 setCursor( tqsizeFDiagCursor );
2712 case PositionBottomLeft:
2713 case PositionTopRight:
2714 setCursor( tqsizeBDiagCursor );
2717 case PositionBottom:
2718 setCursor( tqsizeVerCursor );
2722 setCursor( tqsizeHorCursor );
2726 setCursor( tqsizeAllCursor );
2728 setCursor( tqarrowCursor );
2735void Client::setCursor(
const TQCursor& c )
2737 if( c.handle() == cursor.handle())
2740 if( decoration != NULL )
2741 decoration->widget()->setCursor( cursor );
2742 XDefineCursor( tqt_xdisplay(), frameId(), cursor.handle());
2745Client::Position Client::mousePosition(
const TQPoint& p )
const
2747 if( decoration != NULL )
2748 return decoration->mousePosition( p );
2749 return PositionCenter;
2752void Client::updateAllowedActions(
bool force )
2754 if( !isManaged() && !force )
2756 unsigned long old_allowed_actions = allowed_actions;
2757 allowed_actions = 0;
2759 allowed_actions |= NET::ActionMove;
2761 allowed_actions |= NET::ActionResize;
2763 allowed_actions |= NET::ActionMinimize;
2765 allowed_actions |= NET::ActionShade;
2767 if( isMaximizable())
2768 allowed_actions |= NET::ActionMax;
2769 if( userCanSetFullScreen())
2770 allowed_actions |= NET::ActionFullScreen;
2771 allowed_actions |= NET::ActionChangeDesktop;
2773 allowed_actions |= NET::ActionClose;
2774 if( old_allowed_actions == allowed_actions )
2777 info->setAllowedActions( allowed_actions );
2781void Client::autoRaise()
2783 workspace()->raiseClient(
this );
2787void Client::cancelAutoRaise()
2789 delete autoRaiseTimer;
2793void Client::setOpacity(
bool translucent, uint opacity)
2799 if (!translucent || opacity == 0xFFFFFFFF)
2801 opacity_ = 0xFFFFFFFF;
2802 XDeleteProperty (tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2803 XDeleteProperty (tqt_xdisplay(), window(), atoms->net_wm_window_opacity);
2806 if(opacity == opacity_)
2809 long data = opacity;
2810 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2811 XChangeProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2815void Client::setShadowSize(uint shadowSize)
2819 long data = shadowSize;
2820 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2823void Client::updateOpacity()
2826 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2830 if( ruleOpacityActive() )
2831 setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2833 setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2837 ClientList tmpGroupMembers = group()->members();
2838 ClientList activeGroupMembers;
2839 activeGroupMembers.append(
this);
2840 tmpGroupMembers.remove(
this);
2841 ClientList::Iterator it = tmpGroupMembers.begin();
2842 while (it != tmpGroupMembers.end())
2845 if ((*it) !=
this && (*it)->isBMP())
2849 if ((*it)->touches(
this))
2852 if( ruleOpacityActive() )
2853 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2855 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2857 (*it)->setShadowSize(options->activeWindowShadowSize);
2858 activeGroupMembers.append(*it);
2859 tmpGroupMembers.remove(it);
2860 it = tmpGroupMembers.begin();
2866 for( ClientList::ConstIterator it2 = activeGroupMembers.begin(); it2 != activeGroupMembers.end(); it2++ )
2868 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2871 if( ruleOpacityActive() )
2872 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2874 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2875 (*it)->setShadowSize(options->activeWindowShadowSize);
2876 activeGroupMembers.append(*it);
2877 tmpGroupMembers.remove(it);
2878 it = tmpGroupMembers.begin();
2884 if (found)
continue;
2890 else if (isNormalWindow())
2893 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2894 if ((*it)->isDialog() || (*it)->isUtility())
2896 if( (*it)->ruleOpacityActive() )
2897 (*it)->setOpacity((*it)->ruleOpacityActive() < 0xFFFFFFFF, (*it)->ruleOpacityActive());
2899 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2905 if( ruleOpacityInactive() )
2906 setOpacity(rule_opacity_inactive < 0xFFFFFFFF, rule_opacity_inactive);
2908 setOpacity(options->translucentInactiveWindows && !(
keepAbove() && options->keepAboveAsActive),
2909 options->inactiveWindowOpacity);
2914 ClientList tmpGroupMembers = group()->members();
2915 ClientList inactiveGroupMembers;
2916 inactiveGroupMembers.append(
this);
2917 tmpGroupMembers.remove(
this);
2918 ClientList::Iterator it = tmpGroupMembers.begin();
2919 while ( it != tmpGroupMembers.end() )
2922 if ((*it) !=
this && (*it)->isBMP())
2926 if ((*it)->touches(
this))
2929 if( (*it)->ruleOpacityInactive() )
2930 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2932 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2933 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2935 inactiveGroupMembers.append(*it);
2936 tmpGroupMembers.remove(it);
2937 it = tmpGroupMembers.begin();
2943 for( ClientList::ConstIterator it2 = inactiveGroupMembers.begin(); it2 != inactiveGroupMembers.end(); it2++ )
2945 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2948 if( (*it)->ruleOpacityInactive() )
2949 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2951 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2952 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2954 inactiveGroupMembers.append(*it);
2955 tmpGroupMembers.remove(it);
2956 it = tmpGroupMembers.begin();
2961 if (found)
continue;
2967 else if (isNormalWindow())
2969 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2970 if ((*it)->isUtility())
2972 if( (*it)->ruleOpacityInactive() )
2973 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2975 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2981void Client::updateShadowSize()
2984 if (!(isNormalWindow() || isDialog() || isUtility() ))
2987 setShadowSize(options->activeWindowShadowSize);
2989 setShadowSize(options->inactiveWindowShadowSize);
2992uint Client::ruleOpacityInactive()
2994 return rule_opacity_inactive;
2997uint Client::ruleOpacityActive()
2999 return rule_opacity_active;
3002bool Client::getWindowOpacity()
3004 unsigned char *data = 0;
3007 unsigned long n, left;
3008 result = XGetWindowProperty(tqt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
3009 if (result == Success && data && format == 32 )
3011 opacity_ = *
reinterpret_cast< long*
>( data );
3012 custom_opacity =
true;
3014 XFree ((
char*)data);
3020void Client::setCustomOpacityFlag(
bool custom)
3022 custom_opacity = custom;
3025uint Client::opacity()
3030int Client::opacityPercentage()
3032 return int(100*((
double)opacity_/0xffffffff));
3035bool Client::touches(
const Client* c)
3038 if (y() == c->y() + c->height())
3040 if (y() + height() == c->y())
3042 if (x() == c->x() + c->width())
3044 if (x() + width() == c->x())
3049void Client::setDecoHashProperty(uint topHeight, uint rightWidth, uint bottomHeight, uint leftWidth)
3051 long data = (topHeight < 255 ? topHeight : 255) << 24 |
3052 (rightWidth < 255 ? rightWidth : 255) << 16 |
3053 (bottomHeight < 255 ? bottomHeight : 255) << 8 |
3054 (leftWidth < 255 ? leftWidth : 255);
3055 XChangeProperty(tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
3058void Client::unsetDecoHashProperty()
3060 XDeleteProperty( tqt_xdisplay(), frameId(), atoms->net_wm_window_decohash);
3064kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
3067 return stream <<
"\'NULL_CLIENT\'";
3068 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
3070kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
3074 for( ClientList::ConstIterator it = list.begin();
3086kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
3090 for( ConstClientList::ConstIterator it = list.begin();
3104TQPixmap * twin_get_menu_pix_hack()
3108 p = SmallIcon(
"bx2" );
3114#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)