16 #include <tqapplication.h>
17 #include <tqpainter.h>
18 #include <tqdatetime.h>
22 #include <kstandarddirs.h>
23 #include <tqwhatsthis.h>
25 #include <kiconloader.h>
30 #include "workspace.h"
32 #include "notifications.h"
35 #include <X11/extensions/shape.h>
40 extern Atom qt_wm_state;
41 extern Atom qt_window_role;
42 extern Atom qt_sm_client_id;
45 static const int SHADOW_DELAY = 200;
47 namespace KWinInternal
61 static TQValueList<ShadowRegion> shadowRegions;
94 bridge( new Bridge( this )),
95 move_faked_activity( false ),
96 move_resize_grab_window( None ),
97 transient_for( NULL ),
98 transient_for_id( None ),
99 original_transient_for_id( None ),
101 window_group( None ),
102 in_layer( UnknownLayer ),
104 process_killer( NULL ),
105 user_time( CurrentTime ),
106 allowed_actions( 0 ),
107 postpone_geometry_updates( 0 ),
108 pending_geometry_update( false ),
109 shade_geometry_change( false ),
115 demandAttentionKNotifyTimer( NULL )
121 shadowDelayTimer =
new TQTimer(
this);
122 opacityCache = &activeOpacityCache;
123 shadowAfterClient = NULL;
126 connect(shadowDelayTimer, TQT_SIGNAL(timeout()), TQT_SLOT(drawShadow()));
129 mapping_state = WithdrawnState;
132 mode = PositionCenter;
134 moveResizeMode = FALSE;
138 shade_mode = ShadeNone;
144 motif_noborder =
false;
145 motif_may_move = TRUE;
146 motif_may_resize = TRUE;
147 motif_may_close = TRUE;
148 fullscreen_mode = FullScreenNone;
149 skip_taskbar = FALSE;
150 original_skip_taskbar =
false;
155 user_noborder =
false;
157 ignore_focus_stealing =
false;
158 demands_attention =
false;
159 check_active_modal =
false;
169 max_mode = MaximizeRestore;
170 maxmode_restore = MaximizeRestore;
174 frame_geometry = TQRect( 0, 0, 100, 100 );
175 client_size = TQSize( 100, 100 );
176 custom_opacity =
false;
177 rule_opacity_active = 0;;
178 rule_opacity_inactive = 0;
188 assert(!moveResizeMode);
189 assert( client == None );
190 assert( frame == None && wrapper == None );
191 assert( decoration == NULL );
192 assert( postpone_geometry_updates == 0 );
193 assert( !check_active_modal );
199 void Client::deleteClient( Client* c, allowed_t )
211 workspace()->discardUsedWindowRules(
this,
true );
212 StackingUpdatesBlocker blocker( workspace());
213 if (!custom_opacity) setOpacity(FALSE);
217 drawIntersectingShadows();
219 ++postpone_geometry_updates;
223 setMappingState( WithdrawnState );
227 workspace()->clientHidden(
this );
228 XUnmapWindow( qt_xdisplay(), frameId());
233 workspace()->removeClient(
this, Allowed );
236 info->setDesktop( 0 );
238 info->setState( 0, info->state());
240 XDeleteProperty( qt_xdisplay(), client, atoms->kde_net_wm_user_creation_time);
241 XDeleteProperty( qt_xdisplay(), client, atoms->net_frame_extents );
242 XDeleteProperty( qt_xdisplay(), client, atoms->kde_net_wm_frame_strut );
243 XReparentWindow( qt_xdisplay(), client, workspace()->rootWin(), x(), y());
244 XRemoveFromSaveSet( qt_xdisplay(), client );
245 XSelectInput( qt_xdisplay(), client, NoEventMask );
248 XMapWindow( qt_xdisplay(), client );
255 XUnmapWindow( qt_xdisplay(), client );
258 XDestroyWindow( qt_xdisplay(), wrapper );
260 XDestroyWindow( qt_xdisplay(), frame );
262 --postpone_geometry_updates;
263 checkNonExistentClients();
264 deleteClient(
this, Allowed );
270 void Client::destroyClient()
274 workspace()->discardUsedWindowRules(
this,
true );
275 StackingUpdatesBlocker blocker( workspace());
279 drawIntersectingShadows();
281 ++postpone_geometry_updates;
284 workspace()->clientHidden(
this );
287 workspace()->removeClient(
this, Allowed );
289 XDestroyWindow( qt_xdisplay(), wrapper );
291 XDestroyWindow( qt_xdisplay(), frame );
293 --postpone_geometry_updates;
294 checkNonExistentClients();
295 deleteClient(
this, Allowed );
298 void Client::updateDecoration(
bool check_workspace_pos,
bool force )
300 if( !force && (( decoration == NULL && noBorder())
301 || ( decoration != NULL && !noBorder())))
303 bool do_show =
false;
304 postponeGeometryUpdates(
true );
309 setMask( TQRegion());
310 decoration = workspace()->createDecoration( bridge );
313 decoration->widget()->installEventFilter(
this );
314 XReparentWindow( qt_xdisplay(), decoration->widget()->winId(), frameId(), 0, 0 );
315 decoration->widget()->lower();
316 decoration->borders( border_left, border_right, border_top, border_bottom );
317 options->onlyDecoTranslucent ?
318 setDecoHashProperty(border_top, border_right, border_bottom, border_left):
319 unsetDecoHashProperty();
320 int save_workarea_diff_x = workarea_diff_x;
321 int save_workarea_diff_y = workarea_diff_y;
322 move( calculateGravitation(
false ));
323 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
324 workarea_diff_x = save_workarea_diff_x;
325 workarea_diff_y = save_workarea_diff_y;
330 if( check_workspace_pos )
331 checkWorkspacePosition();
332 postponeGeometryUpdates(
false );
334 decoration->widget()->show();
335 updateFrameExtents();
336 updateOpacityCache();
339 void Client::destroyDecoration()
341 if( decoration != NULL )
345 TQPoint grav = calculateGravitation(
true );
346 border_left = border_right = border_top = border_bottom = 0;
347 setMask( TQRegion());
348 int save_workarea_diff_x = workarea_diff_x;
349 int save_workarea_diff_y = workarea_diff_y;
350 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
352 workarea_diff_x = save_workarea_diff_x;
353 workarea_diff_y = save_workarea_diff_y;
357 void Client::checkBorderSizes()
359 if( decoration == NULL )
361 int new_left, new_right, new_top, new_bottom;
362 decoration->borders( new_left, new_right, new_top, new_bottom );
363 if( new_left == border_left && new_right == border_right
364 && new_top == border_top && new_bottom == border_bottom )
366 GeometryUpdatesPostponer blocker(
this );
367 move( calculateGravitation(
true ));
368 border_left = new_left;
369 border_right = new_right;
370 border_top = new_top;
371 border_bottom = new_bottom;
372 if (border_left != new_left ||
373 border_right != new_right ||
374 border_top != new_top ||
375 border_bottom != new_bottom)
376 options->onlyDecoTranslucent ?
377 setDecoHashProperty(new_top, new_right, new_bottom, new_left):
378 unsetDecoHashProperty();
379 move( calculateGravitation(
false ));
380 plainResize( sizeForClientSize( clientSize()), ForceGeometrySet );
381 checkWorkspacePosition();
384 void Client::detectNoBorder()
386 if( Shape::hasShape( window()))
391 switch( windowType())
413 if( info->windowType( SUPPORTED_WINDOW_TYPES_MASK | NET::OverrideMask ) == NET::Override )
417 void Client::detectShapable()
419 if( Shape::hasShape( window()))
421 switch( windowType())
441 void Client::updateFrameExtents()
444 strut.left = border_left;
445 strut.right = border_right;
446 strut.top = border_top;
447 strut.bottom = border_bottom;
448 info->setFrameExtents( strut );
456 void Client::resizeDecoration(
const TQSize& s )
458 if( decoration == NULL )
460 TQSize oldsize = decoration->widget()->size();
461 decoration->resize( s );
464 TQResizeEvent e( s, oldsize );
465 TQApplication::sendEvent( decoration->widget(), &e );
467 if (!moveResizeMode && options->shadowEnabled(isActive()))
471 updateOpacityCache();
475 bool Client::noBorder()
const
477 return noborder || isFullScreen() || user_noborder || motif_noborder;
480 bool Client::userCanSetNoBorder()
const
482 return !noborder && !isFullScreen() && !isShade();
485 bool Client::isUserNoBorder()
const
487 return user_noborder;
490 void Client::setUserNoBorder(
bool set )
492 if( !userCanSetNoBorder())
494 set = rules()->checkNoBorder(
set );
495 if( user_noborder ==
set )
498 updateDecoration(
true,
false );
502 bool Client::isModalSystemNotification()
const
504 unsigned char *data = 0;
507 unsigned long n, left;
508 result = XGetWindowProperty(qt_xdisplay(), window(), atoms->net_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
509 if (result == Success && data != None && format == 32 )
516 void Client::updateShape()
519 if( shape() && !noBorder())
522 updateDecoration(
true );
524 updateOpacityCache();
527 XShapeCombineShape(qt_xdisplay(), frameId(), ShapeBounding,
528 clientPos().x(), clientPos().y(),
529 window(), ShapeBounding, ShapeSet);
535 if( Shape::version() >= 0x11 )
545 static Window helper_window = None;
546 if( helper_window == None )
547 helper_window = XCreateSimpleWindow( qt_xdisplay(), qt_xrootwin(),
548 0, 0, 1, 1, 0, 0, 0 );
549 XResizeWindow( qt_xdisplay(), helper_window, width(), height());
550 XShapeCombineShape( qt_xdisplay(), helper_window, ShapeInput, 0, 0,
551 frameId(), ShapeBounding, ShapeSet );
552 XShapeCombineShape( qt_xdisplay(), helper_window, ShapeInput,
553 clientPos().x(), clientPos().y(),
554 window(), ShapeBounding, ShapeSubtract );
555 XShapeCombineShape( qt_xdisplay(), helper_window, ShapeInput,
556 clientPos().x(), clientPos().y(),
557 window(), ShapeInput, ShapeUnion );
558 XShapeCombineShape( qt_xdisplay(), frameId(), ShapeInput, 0, 0,
559 helper_window, ShapeInput, ShapeSet );
563 void Client::setMask(
const TQRegion& reg,
int mode )
567 XShapeCombineMask( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
569 else if( mode == X::Unsorted )
570 XShapeCombineRegion( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
571 reg.handle(), ShapeSet );
574 TQMemArray< TQRect > rects = reg.rects();
575 XRectangle* xrects =
new XRectangle[ rects.count() ];
576 for(
unsigned int i = 0;
580 xrects[ i ].x = rects[ i ].x();
581 xrects[ i ].y = rects[ i ].y();
582 xrects[ i ].width = rects[ i ].width();
583 xrects[ i ].height = rects[ i ].height();
585 XShapeCombineRectangles( qt_xdisplay(), frameId(), ShapeBounding, 0, 0,
586 xrects, rects.count(), ShapeSet, mode );
592 TQRegion Client::mask()
const
595 return TQRegion( 0, 0, width(), height());
599 void Client::setShapable(
bool b)
602 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shapable, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &tmp, 1L);
605 void Client::hideClient(
bool hide )
618 if( isSpecialWindow())
620 if( isModalSystemNotification())
624 bool shown_mainwindow =
false;
625 ClientList mainclients = mainClients();
626 for( ClientList::ConstIterator it = mainclients.begin();
627 it != mainclients.end();
630 if( (*it)->isShown(
true ))
631 shown_mainwindow =
true;
633 if( !shown_mainwindow )
639 if( transientFor() != NULL )
641 if( !wantsTabFocus())
651 if( isModalSystemNotification())
665 info->setState(0, NET::Shaded);
667 Notify::raise( Notify::Minimize );
670 if ( mainClients().isEmpty() && isOnCurrentDesktop() && isShown(
true ) && !avoid_animation )
671 animateMinimizeOrUnminimize(
true );
676 updateAllowedActions();
677 workspace()->updateMinimizedOfTransients(
this );
679 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeLast );
682 void Client::unminimize(
bool avoid_animation )
688 info->setState(NET::Shaded, NET::Shaded);
690 Notify::raise( Notify::UnMinimize );
692 if( isOnCurrentDesktop() && isShown(
true ))
694 if( mainClients().isEmpty() && !avoid_animation )
695 animateMinimizeOrUnminimize( FALSE );
698 updateAllowedActions();
699 workspace()->updateMinimizedOfTransients(
this );
703 extern bool blockAnimation;
705 void Client::animateMinimizeOrUnminimize(
bool minimize )
707 if ( blockAnimation )
709 if ( !options->animateMinimize )
712 if( decoration != NULL && decoration->animateMinimize( minimize ))
719 float lf,rf,tf,bf,step;
721 int speed = options->animateMinimizeSpeed;
727 step = 40. * (11 - speed );
729 NETRect r = info->iconGeometry();
730 TQRect icongeom( r.pos.x, r.pos.y, r.size.width, r.size.height );
731 if ( !icongeom.isValid() )
734 TQPixmap pm = animationPixmap( minimize ? width() : icongeom.width() );
736 TQRect before, after;
739 before = TQRect( x(), y(), width(), pm.height() );
740 after = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
744 before = TQRect( icongeom.x(), icongeom.y(), icongeom.width(), pm.height() );
745 after = TQRect( x(), y(), width(), pm.height() );
748 lf = (after.left() - before.left())/step;
749 rf = (after.right() - before.right())/step;
750 tf = (after.top() - before.top())/step;
751 bf = (after.bottom() - before.bottom())/step;
755 TQRect area = before;
763 TQPainter p ( workspace()->desktopWidget() );
764 bool need_to_clear = FALSE;
770 pm = animationPixmap( area.width() );
771 pm2 = TQPixmap::grabWindow( qt_xrootwin(), area.x(), area.y(), area.width(), area.height() );
772 p.drawPixmap( area.x(), area.y(), pm );
775 p.drawPixmap( area2.x(), area2.y(), pm3 );
776 need_to_clear = FALSE;
780 XFlush(qt_xdisplay());
781 XSync( qt_xdisplay(), FALSE );
785 area.setLeft(before.left() + int(diff*lf));
786 area.setRight(before.right() + int(diff*rf));
787 area.setTop(before.top() + int(diff*tf));
788 area.setBottom(before.bottom() + int(diff*bf));
791 if ( area2.intersects( area ) )
792 p.drawPixmap( area2.x(), area2.y(), pm2 );
796 need_to_clear = TRUE;
799 }
while ( t.elapsed() < step);
800 if (area2 == area || need_to_clear )
801 p.drawPixmap( area2.x(), area2.y(), pm2 );
811 TQPixmap Client::animationPixmap(
int w )
813 TQFont font = options->font(isActive());
814 TQFontMetrics fm( font );
815 TQPixmap pm( w, fm.lineSpacing() );
816 pm.fill( options->color(Options::ColorTitleBar, isActive() || isMinimized() ) );
818 p.setPen(options->color(Options::ColorFont, isActive() || isMinimized() ));
819 p.setFont(options->font(isActive()));
820 p.drawText( pm.rect(), AlignLeft|AlignVCenter|SingleLine,
caption() );
825 bool Client::isShadeable()
const
827 return !isSpecialWindow() && !noBorder();
830 void Client::setShade( ShadeMode mode )
834 if( isModalSystemNotification())
836 mode = rules()->checkShade( mode );
837 if( shade_mode == mode )
839 bool was_shade = isShade();
840 ShadeMode was_shade_mode = shade_mode;
842 if( was_shade == isShade())
844 if( decoration != NULL )
845 decoration->shadeChange();
849 if( shade_mode == ShadeNormal )
851 if ( isShown(
true ) && isOnCurrentDesktop())
852 Notify::raise( Notify::ShadeUp );
854 else if( shade_mode == ShadeNone )
856 if( isShown(
true ) && isOnCurrentDesktop())
857 Notify::raise( Notify::ShadeDown );
860 assert( decoration != NULL );
861 GeometryUpdatesPostponer blocker(
this );
863 decoration->borders( border_left, border_right, border_top, border_bottom );
865 int as = options->animateShade? 10 : 1;
871 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
874 shade_geometry_change =
true;
875 TQSize s( sizeForClientSize( TQSize( clientSize())));
876 s.setHeight( border_top + border_bottom );
877 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask );
878 XUnmapWindow( qt_xdisplay(), wrapper );
879 XUnmapWindow( qt_xdisplay(), client );
880 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
886 int step = QMAX( 4, QABS( h - s.height() ) / as )+1;
890 XResizeWindow( qt_xdisplay(), frameId(), s.width(), h );
891 resizeDecoration( TQSize( s.width(), h ));
892 TQApplication::syncX();
893 }
while ( h > s.height() + step );
897 shade_geometry_change =
false;
900 if( was_shade_mode == ShadeHover )
901 workspace()->activateNextClient(
this );
903 workspace()->focusToNull();
907 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shade, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &_shade, 1L);
912 shade_geometry_change =
true;
913 TQSize s( sizeForClientSize( clientSize()));
916 int step = QMAX( 4, QABS( h - s.height() ) / as )+1;
920 XResizeWindow( qt_xdisplay(), frameId(), s.width(), h );
921 resizeDecoration( TQSize( s.width(), h ));
925 TQApplication::syncX();
926 }
while ( h < s.height() - step );
929 shade_geometry_change =
false;
931 if( shade_mode == ShadeHover || shade_mode == ShadeActivated )
933 XMapWindow( qt_xdisplay(), wrapperId());
934 XMapWindow( qt_xdisplay(), window());
935 XDeleteProperty (qt_xdisplay(), client, atoms->net_wm_window_shade);
936 if (options->shadowEnabled(
false))
938 for (ClientList::ConstIterator it = transients().begin();
939 it != transients().end(); ++it)
941 (*it)->removeShadow();
942 (*it)->drawDelayedShadow();
947 workspace()->requestFocus(
this );
949 checkMaximizeGeometry();
950 info->setState( (isShade() && !isMinimized()) ? NET::Shaded : 0, NET::Shaded );
951 info->setState( isShown(
false ) ? 0 : NET::Hidden, NET::Hidden );
953 updateAllowedActions();
954 workspace()->updateMinimizedOfTransients(
this );
955 decoration->shadeChange();
959 void Client::shadeHover()
961 setShade( ShadeHover );
965 void Client::cancelShadeHover()
967 delete shadeHoverTimer;
971 void Client::toggleShade()
974 setShade( shade_mode == ShadeNone ? ShadeNormal : ShadeNone );
977 void Client::updateVisibility()
984 setMappingState( IconicState );
985 info->setState( NET::Hidden, NET::Hidden );
986 setSkipTaskbar(
true,
false );
992 setSkipTaskbar( original_skip_taskbar,
false );
996 setMappingState( IconicState );
997 info->setState( NET::Hidden, NET::Hidden );
1002 info->setState( 0, NET::Hidden );
1003 if( !isOnCurrentDesktop())
1005 setMappingState( IconicState );
1011 bool belongs_to_desktop =
false;
1012 for( ClientList::ConstIterator it = group()->members().begin();
1013 it != group()->members().end();
1015 if( (*it)->isDesktop())
1017 belongs_to_desktop =
true;
1020 if( !belongs_to_desktop && workspace()->showingDesktop())
1021 workspace()->resetShowingDesktop(
true );
1023 setMappingState( IconicState );
1025 setMappingState( NormalState );
1030 void Client::setShadowed(
bool shadowed)
1034 wasShadowed = isShadowed();
1035 shadowMe = options->shadowEnabled(isActive()) ? shadowed :
false;
1045 if (!activeOpacityCache.isNull())
1046 activeOpacityCache.resize(0);
1047 if (!inactiveOpacityCache.isNull())
1048 inactiveOpacityCache.resize(0);
1053 void Client::updateOpacityCache()
1055 if (!activeOpacityCache.isNull())
1056 activeOpacityCache.resize(0);
1057 if (!inactiveOpacityCache.isNull())
1058 inactiveOpacityCache.resize(0);
1060 if (!moveResizeMode) {
1064 drawIntersectingShadows();
1065 if (options->shadowEnabled(isActive()))
1066 drawDelayedShadow();
1074 void Client::drawIntersectingShadows() {
1078 TQValueList<Client *> reshadowClients;
1079 TQValueListIterator<ShadowRegion> it;
1080 TQValueListIterator<Client *> it2;
1082 if (!options->shadowEnabled(
false))
1087 region = shapeBoundingRegion;
1092 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1093 if ((isOnAllDesktops() || (*it).client->isOnCurrentDesktop()) &&
1094 !(*it).region.intersect(region).isEmpty())
1095 reshadowClients.append((*it).client);
1098 for (it2 = reshadowClients.begin(); it2 != reshadowClients.end();
1100 (*it2)->removeShadow();
1101 (*it2)->drawDelayedShadow();
1110 void Client::drawOverlappingShadows(
bool waitForMe)
1114 TQValueList<Client *> reshadowClients;
1115 ClientList stacking_order;
1116 ClientList::ConstIterator it;
1117 TQValueListIterator<ShadowRegion> it2;
1118 TQValueListIterator<Client *> it3;
1120 if (!options->shadowEnabled(
false))
1125 region = shapeBoundingRegion;
1127 stacking_order = workspace()->stackingOrder();
1128 for (it = stacking_order.fromLast(); it != stacking_order.end(); --it) {
1134 while (it != stacking_order.end()) {
1135 if ((*it)->windowType() == NET::Dock) {
1146 for (it2 = shadowRegions.begin(); it2 != shadowRegions.end(); ++it2) {
1147 if ((*it2).client == (*it)) {
1148 if ((isOnAllDesktops() || (*it2).client->isOnCurrentDesktop())
1149 && !(*it2).region.intersect(region).isEmpty())
1150 reshadowClients.append((*it2).client);
1157 for (it3 = reshadowClients.begin(); it3 != reshadowClients.end(); ++it3) {
1158 (*it3)->removeShadow();
1159 if (it3 == reshadowClients.begin()) {
1161 (*it3)->drawShadowAfter(
this);
1163 (*it3)->drawDelayedShadow();
1169 (*it3)->drawShadowAfter(aClient);
1178 void Client::drawDelayedShadow()
1180 shadowDelayTimer->stop();
1181 shadowDelayTimer->start(SHADOW_DELAY,
true);
1187 void Client::drawShadowAfter(Client *after)
1189 shadowAfterClient = after;
1190 connect(after, TQT_SIGNAL(shadowDrawn()), TQT_SLOT(drawShadow()));
1196 void Client::drawShadow()
1200 int i, count, ordering;
1203 if (shadowAfterClient != NULL) {
1204 disconnect(shadowAfterClient, TQT_SIGNAL(shadowDrawn()),
this, TQT_SLOT(drawShadow()));
1205 shadowAfterClient = NULL;
1208 if (!isOnCurrentDesktop())
1215 shapes = XShapeGetRectangles(qt_xdisplay(), frameId(), ShapeBounding,
1219 shapeBoundingRegion = TQRegion(x(), y(), width(), height());
1221 shapeBoundingRegion = TQRegion();
1222 for (i = 0; i < count; i++) {
1224 TQRegion shapeRectangle(shapes[i].x, shapes[i].y, shapes[i].width,
1226 shapeBoundingRegion += shapeRectangle;
1232 shapeBoundingRegion &= TQRegion(0, 0, width(), height());
1233 shapeBoundingRegion.translate(x(), y());
1236 if (!isShadowed() || hidden || isMinimized() ||
1237 maximizeMode() == MaximizeFull ||
1238 !options->shadowWindowType(windowType())) {
1250 TQMemArray<QRgb> pixelData;
1251 TQPixmap shadowPixmap;
1253 TQRegion exposedRegion;
1254 ShadowRegion shadowRegion;
1255 int thickness, xOffset, yOffset;
1257 thickness = options->shadowThickness(isActive());
1258 xOffset = options->shadowXOffset(isActive());
1259 yOffset = options->shadowYOffset(isActive());
1260 opacityCache = active? &activeOpacityCache : &inactiveOpacityCache;
1262 shadow.setRect(x() - thickness + xOffset, y() - thickness + yOffset,
1263 width() + thickness * 2, height() + thickness * 2);
1264 shadowPixmap.resize(shadow.size());
1267 shadowWidget =
new TQWidget(0, 0, (WFlags)(WStyle_Customize | WX11BypassWM));
1268 shadowWidget->setGeometry(shadow);
1269 XSelectInput(qt_xdisplay(), shadowWidget->winId(),
1270 ButtonPressMask | ButtonReleaseMask | StructureNotifyMask);
1271 shadowWidget->installEventFilter(
this);
1275 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1276 shadow.y(), shadow.width(), shadow.height(), thickness,
1278 shadowRegion.region = exposedRegion;
1279 shadowRegion.client =
this;
1280 shadowRegions.append(shadowRegion);
1282 if (opacityCache->isNull())
1283 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1284 exposedRegion, thickness,
1285 options->shadowOpacity(isActive()));
1287 imposeCachedShadow(shadowPixmap, exposedRegion);
1290 TQMemArray<TQRect> exposedRects;
1291 TQMemArray<TQRect>::Iterator it, itEnd;
1292 XRectangle *shadowShapes;
1294 exposedRegion = getExposedRegion(shapeBoundingRegion, shadow.x(),
1295 shadow.y(), shadow.width(), shadow.height(), thickness,
1297 shadowRegion.region = exposedRegion;
1298 shadowRegion.client =
this;
1299 shadowRegions.append(shadowRegion);
1302 exposedRects = exposedRegion.rects();
1304 itEnd = exposedRects.end();
1305 shadowShapes =
new XRectangle[exposedRects.count()];
1306 for (it = exposedRects.begin(); it != itEnd; ++it) {
1307 shadowShapes[i].x = (*it).x();
1308 shadowShapes[i].y = (*it).y();
1309 shadowShapes[i].width = (*it).width();
1310 shadowShapes[i].height = (*it).height();
1313 XShapeCombineRectangles(qt_xdisplay(), shadowWidget->winId(),
1314 ShapeBounding, -x() + thickness - xOffset,
1315 -y() + thickness - yOffset, shadowShapes, i, ShapeSet,
1317 delete [] shadowShapes;
1319 if (opacityCache->isNull())
1320 imposeRegionShadow(shadowPixmap, shapeBoundingRegion,
1321 exposedRegion, thickness,
1322 options->shadowOpacity(isActive()));
1324 imposeCachedShadow(shadowPixmap, exposedRegion);
1331 shadowWidget->setErasePixmap(shadowPixmap);
1336 ClientList stacking_order = workspace()->stackingOrder();
1337 for (ClientList::ConstIterator it = stacking_order.begin(); it != stacking_order.end(); ++it)
1338 if ((*it)->isDesktop())
1341 shadows[0] = (*it)->frameId();
1342 shadows[1] = shadowWidget->winId();
1346 shadows[0] = frameId();
1347 if (shadowWidget != NULL)
1348 shadows[1] = shadowWidget->winId();
1351 XRestackWindows(qt_xdisplay(), shadows, 2);
1355 XMapWindow(qt_xdisplay(), shadowWidget->winId());
1364 void Client::removeShadow()
1366 TQValueList<ShadowRegion>::Iterator it;
1368 shadowDelayTimer->stop();
1370 if (shadowWidget != NULL) {
1371 for (it = shadowRegions.begin(); it != shadowRegions.end(); ++it)
1372 if ((*it).client ==
this) {
1373 shadowRegions.remove(it);
1376 delete shadowWidget;
1377 shadowWidget = NULL;
1385 TQRegion Client::getExposedRegion(TQRegion occludedRegion,
int x,
int y,
int w,
1386 int h,
int thickness,
int xOffset,
int yOffset)
1388 TQRegion exposedRegion;
1390 exposedRegion = TQRegion(x, y, w, h);
1391 exposedRegion -= occludedRegion;
1393 if (thickness > 0) {
1396 TQMemArray<TQRect> occludedRects;
1397 TQMemArray<TQRect>::Iterator it, itEnd;
1398 TQRegion shadowRegion;
1400 occludedRects = occludedRegion.rects();
1401 itEnd = occludedRects.end();
1402 for (it = occludedRects.begin(); it != itEnd; ++it) {
1406 it->setTop(it->top() - thickness + yOffset);
1407 it->setLeft(it->left() - thickness + xOffset);
1408 it->setRight(it->right() + thickness + xOffset);
1409 it->setBottom(it->bottom() + thickness + yOffset);
1410 shadowRegion += TQRegion(*it);
1412 exposedRegion -= exposedRegion - shadowRegion;
1415 return exposedRegion;
1421 void Client::imposeCachedShadow(TQPixmap &pixmap, TQRegion exposed)
1425 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1426 int subW, subH, w, h, x, y, zeroX, zeroY;
1428 TQMemArray<TQRect>::Iterator it, itEnd;
1429 TQMemArray<TQRect> rectangles;
1432 int thickness, windowX, windowY, xOffset, yOffset;
1434 rectangles = exposed.rects();
1435 rootWindow = qt_xrootwin();
1436 thickness = options->shadowThickness(isActive());
1437 windowX = this->x();
1438 windowY = this->y();
1439 xOffset = options->shadowXOffset(isActive());
1440 yOffset = options->shadowYOffset(isActive());
1441 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1443 h = pixmap.height();
1445 itEnd = rectangles.end();
1446 for (it = rectangles.begin(); it != itEnd; ++it) {
1447 subW = (*it).width();
1448 subH = (*it).height();
1449 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1451 zeroX = (*it).x() - windowX + thickness - xOffset;
1452 zeroY = (*it).y() - windowY + thickness - yOffset;
1453 image = subPixmap.convertToImage();
1455 for (x = 0; x < subW; x++) {
1456 for (y = 0; y < subH; y++) {
1457 opacity = (*(opacityCache))[(zeroY + y) * w + zeroX + x];
1458 pixel = image.pixel(x, y);
1459 pixelRed = tqRed(pixel);
1460 pixelGreen = tqGreen(pixel);
1461 pixelBlue = tqBlue(pixel);
1462 image.setPixel(x, y,
1463 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1464 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1465 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1469 subPixmap.convertFromImage(image);
1470 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1477 void Client::imposeRegionShadow(TQPixmap &pixmap, TQRegion occluded,
1478 TQRegion exposed,
int thickness,
double maxOpacity)
1480 register int distance, intersectCount, i, j, x, y;
1482 double decay, factor, opacity;
1483 int red, green, blue, pixelRed, pixelGreen, pixelBlue;
1484 int halfMaxIntersects, lineIntersects, maxIntersects, maxY;
1485 int irBottom, irLeft, irRight, irTop, yIncrement;
1486 int subW, subH, w, h, zeroX, zeroY;
1488 TQMemArray<TQRect>::Iterator it, itEnd;
1489 TQMemArray<TQRect> rectangles;
1492 int windowX, windowY, xOffset, yOffset;
1494 rectangles = exposed.rects();
1495 rootWindow = qt_xrootwin();
1496 windowX = this->x();
1497 windowY = this->y();
1498 xOffset = options->shadowXOffset(isActive());
1499 yOffset = options->shadowYOffset(isActive());
1500 options->shadowColour(isActive()).rgb(&red, &green, &blue);
1501 maxIntersects = thickness * thickness * 4 + (thickness * 4) + 1;
1502 halfMaxIntersects = maxIntersects / 2;
1503 lineIntersects = thickness * 2 + 1;
1504 factor = maxIntersects / maxOpacity;
1505 decay = (lineIntersects / 0.0125 - factor) / pow((
double)maxIntersects, 3.0);
1507 h = pixmap.height();
1508 xOffset = options->shadowXOffset(isActive());
1509 yOffset = options->shadowYOffset(isActive());
1511 opacityCache->resize(0);
1512 opacityCache->resize(w * h);
1513 occluded.translate(-windowX + thickness, -windowY + thickness);
1515 itEnd = rectangles.end();
1516 for (it = rectangles.begin(); it != itEnd; ++it) {
1517 subW = (*it).width();
1518 subH = (*it).height();
1519 subPixmap = TQPixmap::grabWindow(rootWindow, (*it).x(), (*it).y(),
1522 zeroX = (*it).x() - windowX + thickness - xOffset;
1523 zeroY = (*it).y() - windowY + thickness - yOffset;
1524 image = subPixmap.convertToImage();
1530 for (x = 0; x < subW; x++) {
1531 irLeft = zeroX + x - thickness;
1532 irRight = zeroX + x + thickness;
1537 irTop = zeroY + y - thickness * yIncrement;
1540 irBottom = zeroY + y + thickness * yIncrement;
1542 if (opacity == -1) {
1547 for (j = irTop; j != irBottom; j += yIncrement) {
1550 for (i = irLeft; i <= irRight; i++) {
1551 if (occluded.contains(TQPoint(i, j)))
1557 if (intersectCount < 0)
1560 for (i = irLeft; i <= irRight; i++) {
1561 if (occluded.contains(TQPoint(i, irBottom)))
1566 distance = maxIntersects - intersectCount;
1567 opacity = intersectCount / (factor + pow((
double)distance, 3.0) * decay);
1569 (*(opacityCache))[(zeroY + y) * w + zeroX + x] = opacity;
1570 pixel = image.pixel(x, y);
1571 pixelRed = tqRed(pixel);
1572 pixelGreen = tqGreen(pixel);
1573 pixelBlue = tqBlue(pixel);
1574 image.setPixel(x, y,
1575 tqRgb((
int)(pixelRed + (red - pixelRed) * opacity),
1576 (
int)(pixelGreen + (green - pixelGreen) * opacity),
1577 (
int)(pixelBlue + (blue - pixelBlue) * opacity)));
1579 for (i = irLeft; i <= irRight; i++) {
1580 if (occluded.contains(TQPoint(i, irTop)))
1588 irTop += yIncrement;
1589 for (j = irTop; j != irBottom; j += yIncrement) {
1590 if (occluded.contains(TQPoint(irLeft, j)))
1594 for (j = irTop; j != irBottom; j += yIncrement) {
1595 if (occluded.contains(TQPoint(irRight, j)))
1608 subPixmap.convertFromImage(image);
1609 bitBlt(&pixmap, zeroX, zeroY, &subPixmap);
1617 void Client::setMappingState(
int s)
1619 assert( client != None );
1620 assert( !deleting || s == WithdrawnState );
1621 if( mapping_state == s )
1623 bool was_unmanaged = ( mapping_state == WithdrawnState );
1625 if( mapping_state == WithdrawnState )
1627 XDeleteProperty( qt_xdisplay(), window(), qt_wm_state );
1630 assert( s == NormalState || s == IconicState );
1632 unsigned long data[2];
1633 data[0] = (
unsigned long) s;
1634 data[1] = (
unsigned long) None;
1635 XChangeProperty(qt_xdisplay(), window(), qt_wm_state, qt_wm_state, 32,
1636 PropModeReplace, (
unsigned char *)data, 2);
1639 postponeGeometryUpdates(
false );
1646 void Client::rawShow()
1648 if( decoration != NULL )
1649 decoration->widget()->show();
1650 XMapWindow( qt_xdisplay(), frame );
1653 XMapWindow( qt_xdisplay(), wrapper );
1654 XMapWindow( qt_xdisplay(), client );
1656 if (options->shadowEnabled(isActive()))
1657 drawDelayedShadow();
1665 void Client::rawHide()
1674 drawIntersectingShadows();
1675 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask );
1676 XUnmapWindow( qt_xdisplay(), frame );
1677 XUnmapWindow( qt_xdisplay(), wrapper );
1678 XUnmapWindow( qt_xdisplay(), client );
1679 XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask );
1680 if( decoration != NULL )
1681 decoration->widget()->hide();
1682 workspace()->clientHidden(
this );
1685 void Client::sendClientMessage(Window w, Atom a, Atom protocol,
long data1,
long data2,
long data3)
1690 memset(&ev, 0,
sizeof(ev));
1691 ev.xclient.type = ClientMessage;
1692 ev.xclient.window = w;
1693 ev.xclient.message_type = a;
1694 ev.xclient.format = 32;
1695 ev.xclient.data.l[0] = protocol;
1696 ev.xclient.data.l[1] = GET_QT_X_TIME();
1697 ev.xclient.data.l[2] = data1;
1698 ev.xclient.data.l[3] = data2;
1699 ev.xclient.data.l[4] = data3;
1701 if (w == qt_xrootwin())
1702 mask = SubstructureRedirectMask;
1703 XSendEvent(qt_xdisplay(), w, False, mask, &ev);
1709 bool Client::isCloseable()
const
1711 if( isModalSystemNotification())
1713 return rules()->checkCloseable( motif_may_close && !isSpecialWindow());
1726 if ( Pdeletewindow )
1728 Notify::raise( Notify::Close );
1729 sendClientMessage( window(), atoms->wm_protocols, atoms->wm_delete_window);
1746 kdDebug( 1212 ) <<
"Client::killWindow():" <<
caption() << endl;
1749 Notify::raise( Notify::Close );
1752 Notify::raise( Notify::TransDelete );
1753 if( isNormalWindow())
1754 Notify::raise( Notify::Delete );
1755 killProcess(
false );
1757 XKillClient(qt_xdisplay(), window() );
1764 void Client::pingWindow()
1768 if( options->killPingTimeout == 0 )
1770 if( ping_timer != NULL )
1772 ping_timer =
new TQTimer(
this );
1773 connect( ping_timer, TQT_SIGNAL( timeout()), TQT_SLOT( pingTimeout()));
1774 ping_timer->start( options->killPingTimeout,
true );
1775 ping_timestamp = GET_QT_X_TIME();
1776 workspace()->sendPingToWindow( window(), ping_timestamp );
1779 void Client::gotPing( Time timestamp )
1782 if( NET::timestampCompare( timestamp, ping_timestamp ) != 0 )
1786 if( process_killer != NULL )
1788 process_killer->kill();
1789 delete process_killer;
1790 process_killer = NULL;
1794 void Client::pingTimeout()
1796 kdDebug( 1212 ) <<
"Ping timeout:" <<
caption() << endl;
1799 killProcess(
true, ping_timestamp );
1802 void Client::killProcess(
bool ask, Time timestamp )
1804 if( process_killer != NULL )
1806 Q_ASSERT( !ask || timestamp != CurrentTime );
1808 pid_t pid = info->pid();
1809 if( pid <= 0 || machine.isEmpty())
1811 kdDebug( 1212 ) <<
"Kill process:" << pid <<
"(" << machine <<
")" << endl;
1814 if( machine !=
"localhost" )
1817 proc <<
"xon" << machine <<
"kill" << pid;
1818 proc.start( KProcess::DontCare );
1821 ::kill( pid, SIGTERM );
1825 process_killer =
new KProcess(
this );
1826 *process_killer << KStandardDirs::findExe(
"kwin_killer_helper" )
1827 <<
"--pid" << TQCString().setNum( pid ) <<
"--hostname" << machine
1828 <<
"--windowname" <<
caption().utf8()
1829 <<
"--applicationname" << resourceClass()
1830 <<
"--wid" << TQCString().setNum( window())
1831 <<
"--timestamp" << TQCString().setNum( timestamp );
1832 connect( process_killer, TQT_SIGNAL( processExited( KProcess* )),
1833 TQT_SLOT( processKillerExited()));
1834 if( !process_killer->start( KProcess::NotifyOnExit ))
1836 delete process_killer;
1837 process_killer = NULL;
1843 void Client::processKillerExited()
1845 kdDebug( 1212 ) <<
"Killer exited" << endl;
1846 delete process_killer;
1847 process_killer = NULL;
1850 void Client::setSkipTaskbar(
bool b,
bool from_outside )
1852 int was_wants_tab_focus = wantsTabFocus();
1855 b = rules()->checkSkipTaskbar( b );
1856 original_skip_taskbar = b;
1858 if ( b == skipTaskbar() )
1861 info->setState( b?NET::SkipTaskbar:0, NET::SkipTaskbar );
1862 updateWindowRules();
1863 if( was_wants_tab_focus != wantsTabFocus())
1864 workspace()->updateFocusChains(
this,
1865 isActive() ? Workspace::FocusChainMakeFirst : Workspace::FocusChainUpdate );
1868 void Client::setSkipPager(
bool b )
1870 b = rules()->checkSkipPager( b );
1871 if ( b == skipPager() )
1874 info->setState( b?NET::SkipPager:0, NET::SkipPager );
1875 updateWindowRules();
1878 void Client::setModal(
bool m )
1889 void Client::setDesktop(
int desktop )
1891 if( desktop != NET::OnAllDesktops )
1892 desktop = KMAX( 1, KMIN( workspace()->numberOfDesktops(), desktop ));
1893 desktop = rules()->checkDesktop( desktop );
1894 if( desk == desktop )
1896 int was_desk = desk;
1898 info->setDesktop( desktop );
1899 if(( was_desk == NET::OnAllDesktops ) != ( desktop == NET::OnAllDesktops ))
1901 if ( isShown(
true ))
1902 Notify::raise( isOnAllDesktops() ? Notify::OnAllDesktops : Notify::NotOnAllDesktops );
1903 workspace()->updateOnAllDesktopsOfTransients(
this );
1905 if( decoration != NULL )
1906 decoration->desktopChange();
1907 workspace()->updateFocusChains(
this, Workspace::FocusChainMakeFirst );
1909 updateWindowRules();
1912 void Client::setOnAllDesktops(
bool b )
1914 if(( b && isOnAllDesktops())
1915 || ( !b && !isOnAllDesktops()))
1918 setDesktop( NET::OnAllDesktops );
1920 setDesktop( workspace()->currentDesktop());
1923 bool Client::isOnCurrentDesktop()
const
1925 return isOnDesktop( workspace()->currentDesktop());
1928 int Client::screen()
const
1930 if( !options->xineramaEnabled )
1932 return workspace()->screenNumber( geometry().center());
1935 bool Client::isOnScreen(
int screen )
const
1937 if( !options->xineramaEnabled )
1939 return workspace()->screenGeometry( screen ).intersects( geometry());
1943 void Client::takeActivity(
int flags,
bool handled, allowed_t )
1945 if( !handled || !Ptakeactivity )
1947 if( flags & ActivityFocus )
1948 takeFocus( Allowed );
1949 if( flags & ActivityRaise )
1950 workspace()->raiseClient(
this );
1955 static Time previous_activity_timestamp;
1956 static Client* previous_client;
1957 if( previous_activity_timestamp == GET_QT_X_TIME() && previous_client !=
this )
1959 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for activity" << endl;
1960 kdDebug( 1212 ) << kdBacktrace() << endl;
1962 previous_activity_timestamp = GET_QT_X_TIME();
1963 previous_client =
this;
1965 workspace()->sendTakeActivity(
this, GET_QT_X_TIME(), flags );
1969 void Client::takeFocus( allowed_t )
1972 static Time previous_focus_timestamp;
1973 static Client* previous_client;
1974 if( previous_focus_timestamp == GET_QT_X_TIME() && previous_client !=
this )
1976 kdDebug( 1212 ) <<
"Repeated use of the same X timestamp for focus" << endl;
1977 kdDebug( 1212 ) << kdBacktrace() << endl;
1979 previous_focus_timestamp = GET_QT_X_TIME();
1980 previous_client =
this;
1982 if ( rules()->checkAcceptFocus( input ))
1984 XSetInputFocus( qt_xdisplay(), window(), RevertToPointerRoot, GET_QT_X_TIME() );
1987 sendClientMessage(window(), atoms->wm_protocols, atoms->wm_take_focus);
1988 workspace()->setShouldGetFocus(
this );
2000 if (isModalSystemNotification())
2002 return Pcontexthelp;
2016 sendClientMessage(window(), atoms->wm_protocols, atoms->net_wm_context_help);
2017 TQWhatsThis::enterWhatsThisMode();
2026 void Client::fetchName()
2028 setCaption( readName());
2031 TQString Client::readName()
const
2033 if ( info->name() && info->name()[ 0 ] !=
'\0' )
2034 return TQString::fromUtf8( info->name() );
2036 return KWin::readNameProperty( window(), XA_WM_NAME );
2039 KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate,
const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
2041 void Client::setCaption(
const TQString& s,
bool force )
2043 if ( s != cap_normal || force )
2045 bool reset_name = force;
2046 for(
unsigned int i = 0;
2049 if( !s[ i ].isPrint())
2052 bool was_suffix = ( !cap_suffix.isEmpty());
2053 TQString machine_suffix;
2056 TQString shortcut_suffix = !shortcut().isNull() ? (
" {" + shortcut().toString() +
"}" ) :
"";
2057 cap_suffix = machine_suffix + shortcut_suffix;
2058 if ( ( !isSpecialWindow() || isToolbar()) && workspace()->findClient( FetchNameInternalPredicate(
this )))
2063 cap_suffix = machine_suffix +
" <" + TQString::number(i) +
">" + shortcut_suffix;
2065 }
while ( workspace()->findClient( FetchNameInternalPredicate(
this )));
2066 info->setVisibleName(
caption().utf8() );
2069 if(( was_suffix && cap_suffix.isEmpty()
2072 info->setVisibleName(
"" );
2073 info->setVisibleIconName(
"" );
2075 else if( !cap_suffix.isEmpty() && !cap_iconic.isEmpty())
2076 info->setVisibleIconName( ( cap_iconic + cap_suffix ).utf8() );
2078 if( isManaged() && decoration != NULL )
2079 decoration->captionChange();
2083 void Client::updateCaption()
2085 setCaption( cap_normal,
true );
2088 void Client::fetchIconicName()
2091 if ( info->iconName() && info->iconName()[ 0 ] !=
'\0' )
2092 s = TQString::fromUtf8( info->iconName() );
2094 s = KWin::readNameProperty( window(), XA_WM_ICON_NAME );
2095 if ( s != cap_iconic )
2097 bool was_set = !cap_iconic.isEmpty();
2099 if( !cap_suffix.isEmpty())
2101 if( !cap_iconic.isEmpty())
2102 info->setVisibleIconName( ( s + cap_suffix ).utf8() );
2104 info->setVisibleIconName(
"" );
2113 return full ? cap_normal + cap_suffix : cap_normal;
2116 void Client::getWMHints()
2118 XWMHints *hints = XGetWMHints(qt_xdisplay(), window() );
2120 window_group = None;
2124 if( hints->flags & InputHint )
2125 input = hints->input;
2126 if( hints->flags & WindowGroupHint )
2127 window_group = hints->window_group;
2128 urgency = ( hints->flags & UrgencyHint ) ?
true :
false;
2129 XFree( (
char*)hints );
2133 updateAllowedActions();
2136 void Client::getMotifHints()
2138 bool mnoborder, mresize, mmove, mminimize, mmaximize, mclose;
2139 Motif::readFlags( client, mnoborder, mresize, mmove, mminimize, mmaximize, mclose );
2140 motif_noborder = mnoborder;
2141 if( !hasNETSupport())
2143 motif_may_resize = mresize;
2144 motif_may_move = mmove;
2147 motif_may_resize = motif_may_move =
true;
2150 motif_may_close = mclose;
2152 updateDecoration(
true );
2155 void Client::readIcons( Window win, TQPixmap* icon, TQPixmap* miniicon )
2159 *icon = KWin::icon( win, 32, 32, TRUE, KWin::NETWM | KWin::WMHints );
2160 if( miniicon != NULL )
2161 if( icon == NULL || !icon->isNull())
2162 *miniicon = KWin::icon( win, 16, 16, TRUE, KWin::NETWM | KWin::WMHints );
2164 *miniicon = TQPixmap();
2167 void Client::getIcons()
2170 readIcons( window(), &icon_pix, &miniicon_pix );
2171 if( icon_pix.isNull())
2173 icon_pix = group()->icon();
2174 miniicon_pix = group()->miniIcon();
2176 if( icon_pix.isNull() && isTransient())
2178 ClientList mainclients = mainClients();
2179 for( ClientList::ConstIterator it = mainclients.begin();
2180 it != mainclients.end() && icon_pix.isNull();
2183 icon_pix = (*it)->icon();
2184 miniicon_pix = (*it)->miniIcon();
2187 if( icon_pix.isNull())
2189 icon_pix = KWin::icon( window(), 32, 32, TRUE, KWin::ClassHint | KWin::XApp );
2190 miniicon_pix = KWin::icon( window(), 16, 16, TRUE, KWin::ClassHint | KWin::XApp );
2192 if( isManaged() && decoration != NULL )
2193 decoration->iconChange();
2196 void Client::getWindowProtocols()
2207 if (XGetWMProtocols(qt_xdisplay(), window(), &p, &n))
2209 for (i = 0; i < n; i++)
2210 if (p[i] == atoms->wm_delete_window)
2212 else if (p[i] == atoms->wm_take_focus)
2214 else if (p[i] == atoms->net_wm_take_activity)
2216 else if (p[i] == atoms->net_wm_context_help)
2218 else if (p[i] == atoms->net_wm_ping)
2225 static int nullErrorHandler(Display *, XErrorEvent *)
2235 return getStringProperty(w, qt_window_role).lower();
2243 return getStringProperty(w, qt_sm_client_id);
2251 return getStringProperty(w, XA_WM_COMMAND,
' ');
2261 unsigned long nitems = 0;
2262 unsigned long extra = 0;
2263 unsigned char *data = 0;
2265 XErrorHandler oldHandler = XSetErrorHandler(nullErrorHandler);
2266 status = XGetWindowProperty( qt_xdisplay(), w, atoms->wm_client_leader, 0, 10000,
2267 FALSE, XA_WINDOW, &type, &format,
2268 &nitems, &extra, &data );
2269 XSetErrorHandler(oldHandler);
2270 if (status == Success )
2272 if (data && nitems > 0)
2273 result = *((Window*) data);
2280 void Client::getWmClientLeader()
2292 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2304 if (result.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2309 void Client::getWmClientMachine()
2311 client_machine = getStringProperty(window(), XA_WM_CLIENT_MACHINE);
2312 if( client_machine.isEmpty() && wmClientLeaderWin && wmClientLeaderWin!=window())
2313 client_machine = getStringProperty(wmClientLeaderWin, XA_WM_CLIENT_MACHINE);
2314 if( client_machine.isEmpty())
2315 client_machine =
"localhost";
2324 TQCString result = client_machine;
2327 if( result !=
"localhost" && isLocalMachine( result ))
2328 result =
"localhost";
2339 if (wmClientLeaderWin)
2340 return wmClientLeaderWin;
2344 bool Client::wantsTabFocus()
const
2346 return ( isNormalWindow() || isDialog()) && wantsInput() && !skip_taskbar;
2350 bool Client::wantsInput()
const
2352 return rules()->checkAcceptFocus( input || Ptakefocus );
2355 bool Client::isDesktop()
const
2357 return windowType() == NET::Desktop;
2360 bool Client::isDock()
const
2362 return windowType() == NET::Dock;
2365 bool Client::isTopMenu()
const
2367 return windowType() == NET::TopMenu;
2371 bool Client::isMenu()
const
2373 return windowType() == NET::Menu && !isTopMenu();
2376 bool Client::isToolbar()
const
2378 return windowType() == NET::Toolbar;
2381 bool Client::isSplash()
const
2383 return windowType() == NET::Splash;
2386 bool Client::isUtility()
const
2388 return windowType() == NET::Utility;
2391 bool Client::isDialog()
const
2393 return windowType() == NET::Dialog;
2396 bool Client::isNormalWindow()
const
2398 return windowType() == NET::Normal;
2401 bool Client::isSpecialWindow()
const
2403 return isDesktop() || isDock() || isSplash() || isTopMenu()
2407 NET::WindowType Client::windowType(
bool direct,
int supported_types )
const
2409 NET::WindowType wt = info->windowType( supported_types );
2412 NET::WindowType wt2 = rules()->checkType( wt );
2416 info->setWindowType( wt );
2419 if( wt == NET::Menu )
2424 if( x() == 0 && y() < 0 && y() > -10 && height() < 100
2425 && abs( width() - workspace()->clientArea( FullArea,
this ).width()) < 10 )
2429 const char*
const oo_prefix =
"openoffice.org";
2431 if( tqstrncmp( resourceClass(), oo_prefix, strlen( oo_prefix )) == 0 && wt == NET::Dialog )
2433 if( wt == NET::Unknown )
2434 wt = isTransient() ? NET::Dialog : NET::Normal;
2442 void Client::setCursor( Position m )
2450 case PositionTopLeft:
2451 case PositionBottomRight:
2452 setCursor( tqsizeFDiagCursor );
2454 case PositionBottomLeft:
2455 case PositionTopRight:
2456 setCursor( tqsizeBDiagCursor );
2459 case PositionBottom:
2460 setCursor( tqsizeVerCursor );
2464 setCursor( tqsizeHorCursor );
2468 setCursor( tqsizeAllCursor );
2470 setCursor( tqarrowCursor );
2476 void Client::setCursor(
const TQCursor& c )
2478 if( c.handle() == cursor.handle())
2481 if( decoration != NULL )
2482 decoration->widget()->setCursor( cursor );
2483 XDefineCursor( qt_xdisplay(), frameId(), cursor.handle());
2486 Client::Position Client::mousePosition(
const TQPoint& p )
const
2488 if( decoration != NULL )
2489 return decoration->mousePosition( p );
2490 return PositionCenter;
2493 void Client::updateAllowedActions(
bool force )
2495 if( !isManaged() && !force )
2497 unsigned long old_allowed_actions = allowed_actions;
2498 allowed_actions = 0;
2500 allowed_actions |= NET::ActionMove;
2502 allowed_actions |= NET::ActionResize;
2504 allowed_actions |= NET::ActionMinimize;
2506 allowed_actions |= NET::ActionShade;
2508 if( isMaximizable())
2509 allowed_actions |= NET::ActionMax;
2510 if( userCanSetFullScreen())
2511 allowed_actions |= NET::ActionFullScreen;
2512 allowed_actions |= NET::ActionChangeDesktop;
2514 allowed_actions |= NET::ActionClose;
2515 if( old_allowed_actions == allowed_actions )
2518 info->setAllowedActions( allowed_actions );
2522 void Client::autoRaise()
2524 workspace()->raiseClient(
this );
2528 void Client::cancelAutoRaise()
2530 delete autoRaiseTimer;
2534 void Client::setOpacity(
bool translucent, uint opacity)
2540 if (!translucent || opacity == 0xFFFFFFFF)
2542 opacity_ = 0xFFFFFFFF;
2543 XDeleteProperty (qt_xdisplay(), frameId(), atoms->net_wm_window_opacity);
2544 XDeleteProperty (qt_xdisplay(), window(), atoms->net_wm_window_opacity);
2547 if(opacity == opacity_)
2550 long data = opacity;
2551 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2552 XChangeProperty(qt_xdisplay(), window(), atoms->net_wm_window_opacity, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2556 void Client::setShadowSize(uint shadowSize)
2560 long data = shadowSize;
2561 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_shadow, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2564 void Client::updateOpacity()
2567 if (!(isNormalWindow() || isDialog() || isUtility() )|| custom_opacity)
2571 if( ruleOpacityActive() )
2572 setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2574 setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2578 ClientList tmpGroupMembers = group()->members();
2579 ClientList activeGroupMembers;
2580 activeGroupMembers.append(
this);
2581 tmpGroupMembers.remove(
this);
2582 ClientList::Iterator it = tmpGroupMembers.begin();
2583 while (it != tmpGroupMembers.end())
2586 if ((*it) !=
this && (*it)->isBMP())
2590 if ((*it)->touches(
this))
2593 if( ruleOpacityActive() )
2594 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2596 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2598 (*it)->setShadowSize(options->activeWindowShadowSize);
2599 activeGroupMembers.append(*it);
2600 tmpGroupMembers.remove(it);
2601 it = tmpGroupMembers.begin();
2607 for( ClientList::ConstIterator it2 = activeGroupMembers.begin(); it2 != activeGroupMembers.end(); it2++ )
2609 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2612 if( ruleOpacityActive() )
2613 (*it)->setOpacity(rule_opacity_active < 0xFFFFFFFF, rule_opacity_active);
2615 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2616 (*it)->setShadowSize(options->activeWindowShadowSize);
2617 activeGroupMembers.append(*it);
2618 tmpGroupMembers.remove(it);
2619 it = tmpGroupMembers.begin();
2625 if (found)
continue;
2631 else if (isNormalWindow())
2634 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2635 if ((*it)->isDialog() || (*it)->isUtility())
2636 if( (*it)->ruleOpacityActive() )
2637 (*it)->setOpacity((*it)->ruleOpacityActive() < 0xFFFFFFFF, (*it)->ruleOpacityActive());
2639 (*it)->setOpacity(options->translucentActiveWindows, options->activeWindowOpacity);
2644 if( ruleOpacityInactive() )
2645 setOpacity(rule_opacity_inactive < 0xFFFFFFFF, rule_opacity_inactive);
2647 setOpacity(options->translucentInactiveWindows && !(
keepAbove() && options->keepAboveAsActive),
2648 options->inactiveWindowOpacity);
2653 ClientList tmpGroupMembers = group()->members();
2654 ClientList inactiveGroupMembers;
2655 inactiveGroupMembers.append(
this);
2656 tmpGroupMembers.remove(
this);
2657 ClientList::Iterator it = tmpGroupMembers.begin();
2658 while ( it != tmpGroupMembers.end() )
2661 if ((*it) !=
this && (*it)->isBMP())
2665 if ((*it)->touches(
this))
2668 if( (*it)->ruleOpacityInactive() )
2669 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2671 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2672 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2674 inactiveGroupMembers.append(*it);
2675 tmpGroupMembers.remove(it);
2676 it = tmpGroupMembers.begin();
2682 for( ClientList::ConstIterator it2 = inactiveGroupMembers.begin(); it2 != inactiveGroupMembers.end(); it2++ )
2684 if ((*it2) !=
this && (*it2) != (*it) && (*it)->touches(*it2))
2687 if( (*it)->ruleOpacityInactive() )
2688 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2690 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2691 (*it)->setShadowSize(options->inactiveWindowShadowSize);
2693 inactiveGroupMembers.append(*it);
2694 tmpGroupMembers.remove(it);
2695 it = tmpGroupMembers.begin();
2700 if (found)
continue;
2706 else if (isNormalWindow())
2708 for( ClientList::ConstIterator it = group()->members().begin(); it != group()->members().end(); it++ )
2709 if ((*it)->isUtility())
2710 if( (*it)->ruleOpacityInactive() )
2711 (*it)->setOpacity((*it)->ruleOpacityInactive() < 0xFFFFFFFF, (*it)->ruleOpacityInactive());
2713 (*it)->setOpacity(options->translucentInactiveWindows && !((*it)->keepAbove() && options->keepAboveAsActive), options->inactiveWindowOpacity);
2718 void Client::updateShadowSize()
2721 if (!(isNormalWindow() || isDialog() || isUtility() ))
2724 setShadowSize(options->activeWindowShadowSize);
2726 setShadowSize(options->inactiveWindowShadowSize);
2729 uint Client::ruleOpacityInactive()
2731 return rule_opacity_inactive;
2734 uint Client::ruleOpacityActive()
2736 return rule_opacity_active;
2739 bool Client::getWindowOpacity()
2741 unsigned char *data = 0;
2744 unsigned long n, left;
2745 result = XGetWindowProperty(qt_xdisplay(), window(), atoms->net_wm_window_opacity, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, &data);
2746 if (result == Success && data != None && format == 32 )
2748 opacity_ = *
reinterpret_cast< long*
>( data );
2749 custom_opacity =
true;
2751 XFree ((
char*)data);
2757 void Client::setCustomOpacityFlag(
bool custom)
2759 custom_opacity = custom;
2762 uint Client::opacity()
2767 int Client::opacityPercentage()
2769 return int(100*((
double)opacity_/0xffffffff));
2772 bool Client::touches(
const Client* c)
2775 if (y() == c->y() + c->height())
2777 if (y() + height() == c->y())
2779 if (x() == c->x() + c->width())
2781 if (x() + width() == c->x())
2786 void Client::setDecoHashProperty(uint topHeight, uint rightWidth, uint bottomHeight, uint leftWidth)
2788 long data = (topHeight < 255 ? topHeight : 255) << 24 |
2789 (rightWidth < 255 ? rightWidth : 255) << 16 |
2790 (bottomHeight < 255 ? bottomHeight : 255) << 8 |
2791 (leftWidth < 255 ? leftWidth : 255);
2792 XChangeProperty(qt_xdisplay(), frameId(), atoms->net_wm_window_decohash, XA_CARDINAL, 32, PropModeReplace, (
unsigned char *) &data, 1L);
2795 void Client::unsetDecoHashProperty()
2797 XDeleteProperty( qt_xdisplay(), frameId(), atoms->net_wm_window_decohash);
2801 kdbgstream& operator<<( kdbgstream& stream,
const Client* cl )
2804 return stream <<
"\'NULL_CLIENT\'";
2805 return stream <<
"\'ID:" << cl->window() <<
";WMCLASS:" << cl->resourceClass() <<
":" << cl->resourceName() <<
";Caption:" << cl->caption() <<
"\'";
2807 kdbgstream& operator<<( kdbgstream& stream,
const ClientList& list )
2811 for( ClientList::ConstIterator it = list.begin();
2823 kdbgstream& operator<<( kdbgstream& stream,
const ConstClientList& list )
2827 for( ConstClientList::ConstIterator it = list.begin();
2841 TQPixmap * kwin_get_menu_pix_hack()
2845 p = SmallIcon(
"bx2" );
2851 #include "client.moc"