Index: trunk/kdebase/kwin/client.h =================================================================== --- trunk/kdebase/kwin/client.h (revision 255681) +++ trunk/kdebase/kwin/client.h (revision 255682) @@ -1,807 +1,808 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ #ifndef KWIN_CLIENT_H #define KWIN_CLIENT_H #include "utils.h" #include "options.h" #include "workspace.h" #include "kdecoration.h" #include #include #include #include #include #include #include #include #include #include class QTimer; class KProcess; class KStartupInfoData; namespace KWinInternal { class Workspace; class Client; class WinInfo; class SessionInfo; class Bridge; class Client : public QObject, public KDecorationDefines { Q_OBJECT public: Client( Workspace *ws ); Window window() const; Window frameId() const; Window wrapperId() const; Window decorationId() const; Workspace* workspace() const; const Client* transientFor() const; Client* transientFor(); bool isTransient() const; bool groupTransient() const; ClientList mainClients() const; // call once before loop bool hasTransient( const Client* c, bool indirect ) const; const ClientList& transients() const; void checkTransient( Window w ); Client* findModal(); const Group* group() const; Group* group(); // prefer isXXX() instead NET::WindowType windowType( bool strict = false, int supported_types = SUPPORTED_WINDOW_TYPES_MASK ) const; QRect geometry() const; QSize size() const; QPoint pos() const; QRect rect() const; int x() const; int y() const; int width() const; int height() const; QPoint clientPos() const; // inside of geometry() QSize clientSize() const; void windowEvent( XEvent* e ); virtual bool eventFilter( QObject* o, QEvent* e ); bool manage( Window w, bool isMapped ); void releaseWindow( bool on_shutdown = false ); QSize adjustedSize( const QSize& ) const; QPixmap icon() const; QPixmap miniIcon() const; bool isActive() const; void setActive( bool ); int desktop() const; void setDesktop( int ); bool isOnDesktop( int d ) const; bool isOnCurrentDesktop() const; bool isOnAllDesktops() const; void setOnAllDesktops( bool set ); // !isShade() && !isMinimized() && not hidden, i.e. normally visible on some virtual desktop // SELI this may possibly clash with QWidget::isShown(), as long as Client is a QWidget bool isShown() const; enum ShadeMode { ShadeNone, // not shaded ShadeNormal, // normally shaded - isShade() is true only here ShadeHover, // "shaded", but visible due to hover unshade ShadeActivated // "shaded", but visible due to alt+tab to the window }; bool isShade() const; void setShade( ShadeMode mode ); bool isShadeable() const; bool isMinimized() const; bool isMaximizable() const; QRect geometryRestore() const; MaximizeMode maximizeMode() const; bool isMinimizable() const; void setMaximize( bool vertically, bool horizontally ); void setFullScreen( bool set, bool user ); bool isFullScreen() const; bool isFullScreenable() const; bool userCanSetFullScreen() const; QRect geometryFSRestore() const { return geom_fs_restore; } // only for session saving int fullScreenMode() const { return fullscreen_mode; } // only for session saving bool isUserNoBorder() const; void setUserNoBorder( bool set ); bool userCanSetNoBorder() const; bool noBorder() const; bool skipTaskbar( bool from_outside = false ) const; void setSkipTaskbar( bool set, bool from_outside ); bool skipPager() const; void setSkipPager( bool ); bool keepAbove() const; void setKeepAbove( bool ); bool keepBelow() const; void setKeepBelow( bool ); Layer layer() const; Layer belongsToLayer() const; void invalidateLayer(); void setModal( bool modal ); bool isModal() const; bool storeSettings() const; void setStoreSettings( bool ); // auxiliary functions, depend on the windowType bool wantsTabFocus() const; bool wantsInput() const; bool hasNETSupport() const; bool isMovable() const; bool isDesktop() const; bool isDock() const; bool isToolbar() const; bool isTopMenu() const; bool isMenu() const; bool isNormalWindow() const; // normal as in 'NET::Normal or NET::Unknown non-transient' bool isDialog() const; bool isSplash() const; bool isUtility() const; bool isOverride() const; // not override redirect, but NET::Override // returns true for "special" windows and false for windows which are "normal" // (normal=window which has a border, can be moved by the user, can be closed, etc.) // true for Desktop, Dock, Splash, Override and TopMenu (and Toolbar??? - for now) // false for Normal, Dialog, Utility and Menu (and Toolbar??? - not yet) TODO bool isSpecialWindow() const; bool isResizable() const; bool isCloseable() const; // may be closed by the user (may have a close button) void takeFocus( bool force, allowed_t ); void demandAttention( bool set = true ); void setMask( const QRegion& r, int mode = X::Unsorted ); void updateDecoration( bool check_workspace_pos, bool force = false, bool delay_delete = false ); void checkBorderSizes(); // shape extensions bool shape() const; void updateShape(); void setGeometry( int x, int y, int w, int h, ForceGeometry_t force = NormalGeometrySet ); void setGeometry( const QRect& r, ForceGeometry_t force = NormalGeometrySet ); void move( int x, int y, ForceGeometry_t force = NormalGeometrySet ); void move( const QPoint & p, ForceGeometry_t force = NormalGeometrySet ); // plainResize() simply resizes void plainResize( int w, int h, ForceGeometry_t force = NormalGeometrySet ); void plainResize( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); void growHorizontal(); void shrinkHorizontal(); void growVertical(); void shrinkVertical(); bool providesContextHelp() const; bool performMouseCommand( Options::MouseCommand, QPoint globalPos ); QCString windowRole() const; QCString sessionId(); QCString resourceName() const; QCString resourceClass() const; QCString wmCommand(); QCString wmClientMachine() const; Window wmClientLeader() const; pid_t pid() const; QRect adjustedClientArea( const QRect& area ) const; Colormap colormap() const; // hides a client - basically like minimize, but without effects, it's simply hidden void hideClient( bool hide ); // updates visibility depending on whether it's on the current desktop void virtualDesktopChange(); QString caption() const; void keyPressEvent( uint key_code ); // FRAME ?? const QPoint calculateGravitation( bool invert, int gravity = 0 ) const; // FRAME public? void NETMoveResize( int x_root, int y_root, NET::Direction direction ); void NETMoveResizeWindow( int flags, int x, int y, int width, int height ); void restackWindow( Window above, int detail, NET::RequestSource source, bool send_event = false ); void gotPing( Time timestamp ); static QCString staticWindowRole(WId); static QCString staticSessionId(WId); static QCString staticWmCommand(WId); static QCString staticWmClientMachine(WId); static Window staticWmClientLeader(WId); void checkWorkspacePosition(); void updateUserTime( Time time = CurrentTime ); Time userTime() const; bool hasUserTimeSupport() const; // does 'delete c;' static void deleteClient( Client* c, allowed_t ); static bool resourceMatch( const Client* c1, const Client* c2 ); static bool belongToSameApplication( const Client* c1, const Client* c2, bool active_hack = false ); static void readIcons( Window win, QPixmap* icon, QPixmap* miniicon ); public slots: // FRAME these probably don't need to be slots anymore void minimize(); void unminimize(); void closeWindow(); void killWindow(); void maximize( MaximizeMode ); void toggleOnAllDesktops(); void toggleShade(); void showContextHelp(); void autoRaise(); void shadeHover(); void destroyClient(); private: friend class Bridge; // FRAME virtual void processMousePressEvent( QMouseEvent* e ); private: // TODO cleanup the order of things in the .h file // use Workspace::createClient() virtual ~Client(); // use destroyClient() or releaseWindow() MousePosition mousePosition( const QPoint& ) const; void setCursor( MousePosition m ); void setCursor( const QCursor& c ); void animateMinimizeOrUnminimize( bool minimize ); QPixmap animationPixmap( int w ); // transparent stuff void drawbound( const QRect& geom ); void clearbound(); void doDrawbound( const QRect& geom, bool clear ); // handlers for X11 events void mapRequestEvent( XMapRequestEvent* e ); void unmapNotifyEvent( XUnmapEvent*e ); void destroyNotifyEvent( XDestroyWindowEvent*e ); void configureRequestEvent( XConfigureRequestEvent* e ); void propertyNotifyEvent( XPropertyEvent* e ); void clientMessageEvent( XClientMessageEvent* e ); bool buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ); bool buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ); bool motionNotifyEvent( Window w, int state, int x, int y, int x_root, int y_root ); void enterNotifyEvent( XCrossingEvent* e ); void leaveNotifyEvent( XCrossingEvent* e ); void visibilityNotifyEvent( XVisibilityEvent* e ); void focusInEvent( XFocusInEvent* e ); void focusOutEvent( XFocusOutEvent* e ); void processDecorationButtonPress( int button, int state, int x, int y, int x_root, int y_root ); private slots: void pingTimeout(); void processKillerExited(); private: // ICCCM 4.1.3.1, 4.1.4 , NETWM 2.5.1 void setMappingState( int s ); int mappingState() const; bool isIconicState() const; bool isNormalState() const; bool isManaged() const; // returns false if this client is not yet managed void updateAllowedActions( bool force = false ); QSize sizeForClientSize( const QSize&, bool ignore_height = FALSE ) const; void changeMaximize( bool horizontal, bool vertical, bool adjust ); void getWmNormalHints(); void getIcons(); void getWmClientLeader(); void fetchName(); void fetchIconicName(); void updateWorkareaDiffs( const QRect& area = QRect()); void checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area ); static int computeWorkareaDiff( int left, int right, int a_left, int a_right ); void configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity = 0 ); // resizeWithChecks() resizes according to gravity, and checks workarea position void resizeWithChecks( int w, int h, ForceGeometry_t force = NormalGeometrySet ); void resizeWithChecks( const QSize& s, ForceGeometry_t force = NormalGeometrySet ); bool startMoveResize(); void finishMoveResize( bool cancel ); void leaveMoveResize(); void handleMoveResize( int x, int y, int x_root, int y_root ); void positionGeometryTip(); bool grabInput(); void ungrabInput(); void updateMouseGrab(); void grabButton( int mod ); void ungrabButton( int mod ); void resetMaximize(); void resizeDecoration( const QSize& s ); void pingWindow(); void killProcess( bool ask, Time timestamp = CurrentTime ); void embedClient( Window w ); void detectNoBorder(); void destroyDecoration( bool delay_delete = false ); void updateFrameStrut(); void rawShow(); // just shows it void rawHide(); // just hides it Time readUserTimeMapTimestamp( const KStartupInfoData* asn_data, const SessionInfo* session ) const; Time readUserCreationTime() const; static bool sameAppWindowRoleMatch( const Client* c1, const Client* c2, bool active_hack ); void startupIdChanged(); Window client; Window wrapper; Window frame; KDecoration* decoration; Workspace* wspace; Bridge* bridge; int desk; bool buttonDown; bool moveResizeMode; bool move_faked_activity; bool unrestrictedMoveResize; bool isMove() const { return moveResizeMode && mode == Center; } bool isResize() const { return moveResizeMode && !isMove(); } MousePosition mode; QPoint moveOffset; QPoint invertedMoveOffset; QRect moveResizeGeom; QRect initialMoveResizeGeom; XSizeHints xSizeHint; void sendSyntheticConfigureNotify(); int mapping_state; void readTransient(); Window verifyTransientFor( Window transient_for, bool set ); void addTransient( Client* cl ); void removeTransient( Client* cl ); void removeFromMainClients(); void cleanGrouping(); void checkGroupTransients(); void setTransient( Window new_transient_for_id ); Client* transient_for; Window transient_for_id; Window original_transient_for_id; ClientList transients_list; // SELI make this ordered in stacking order? ShadeMode shade_mode; uint active :1; uint keep_above : 1; // NET::KeepAbove (was stays_on_top) uint is_shape :1; uint skip_taskbar :1; uint original_skip_taskbar :1; // unaffected by KWin uint Pdeletewindow :1; // does the window understand the DeleteWindow protocol? uint Ptakefocus :1;// does the window understand the TakeFocus protocol? uint Pcontexthelp : 1; // does the window understand the ContextHelp protocol? uint Pping : 1; // does it support _NET_WM_PING? uint input :1; // does the window want input in its wm_hints uint store_settings : 1; uint skip_pager : 1; uint motif_may_resize : 1; uint motif_may_move :1; uint motif_may_close : 1; uint keep_below : 1; // NET::KeepBelow uint minimized : 1; uint hidden : 1; // forcibly hidden by calling hide() uint modal : 1; // NET::Modal uint noborder : 1; uint user_noborder : 1; uint not_obscured : 1; void getWMHints(); void readIcons(); void getWindowProtocols(); QPixmap icon_pix; QPixmap miniicon_pix; QCursor cursor; // FullScreenHack - non-NETWM fullscreen (noborder,size of desktop) // DON'T reorder - saved to config files !!! enum FullScreenMode { FullScreenNone, FullScreenNormal, FullScreenHack }; FullScreenMode fullscreen_mode; MaximizeMode max_mode; QRect geom_restore; QRect geom_fs_restore; int workarea_diff_x, workarea_diff_y; WinInfo* info; QTimer* autoRaiseTimer; QTimer* shadeHoverTimer; Colormap cmap; QCString resource_name; QCString resource_class; QString cap_normal, cap_iconic, cap_suffix; WId wmClientLeaderWin; QCString window_role; void checkGroup(); Group* in_group; Window window_group; Layer in_layer; QTimer* ping_timer; KProcess* process_killer; Time ping_timestamp; Time user_time; bool input_grabbed; unsigned long allowed_actions; QRect frame_geometry; QSize client_size; int block_geometry; // >0 - new geometry is remembered, but not actually set bool shade_geometry_change; int border_left, border_right, border_top, border_bottom; friend struct FetchNameInternalPredicate; void show() { assert( false ); } // SELI remove after Client is no longer QWidget void hide() { assert( false ); } }; // NET WM Protocol handler class class WinInfo : public NETWinInfo { private: typedef KWinInternal::Client Client; // because of NET::Client public: WinInfo( Client* c, Display * display, Window window, Window rwin, const unsigned long pr[], int pr_size ); virtual void changeDesktop(int desktop); virtual void changeState( unsigned long state, unsigned long mask ); private: Client * m_client; }; inline Window Client::window() const { return client; } inline Window Client::frameId() const { return frame; } inline Window Client::wrapperId() const { return wrapper; } inline Window Client::decorationId() const { return decoration != NULL ? decoration->widget()->winId() : None; } inline Workspace* Client::workspace() const { return wspace; } inline const Client* Client::transientFor() const { return transient_for; } inline Client* Client::transientFor() { return transient_for; } inline bool Client::groupTransient() const { return transient_for_id == workspace()->rootWin(); } inline bool Client::isTransient() const { return transient_for_id != None; } inline const ClientList& Client::transients() const { return transients_list; } inline const Group* Client::group() const { return in_group; } inline Group* Client::group() { return in_group; } inline int Client::mappingState() const { return mapping_state; } inline QCString Client::resourceName() const { return resource_name; } inline QCString Client::resourceClass() const { return resource_class; } inline bool Client::isMinimized() const { return minimized; } inline bool Client::isActive() const { return active; } /*! Returns the virtual desktop within the workspace() the client window is located in, 0 if it isn't located on any special desktop (not mapped yet), or NET::OnAllDesktops. Do not use desktop() directly, use isOnDesktop() instead. */ inline int Client::desktop() const { return desk; } inline bool Client::isOnAllDesktops() const { return desk == NET::OnAllDesktops; } /*! Returns whether the client is on the virtual desktop \a d. This is always TRUE for onAllDesktops clients. */ inline bool Client::isOnDesktop( int d ) const { return desk == d || /*desk == 0 ||*/ isOnAllDesktops(); } inline bool Client::isShown() const { return !isMinimized() && !isShade() && !hidden; } inline bool Client::isShade() const { return shade_mode == ShadeNormal; } inline QPixmap Client::icon() const { return icon_pix; } inline QPixmap Client::miniIcon() const { return miniicon_pix; } inline QRect Client::geometryRestore() const { return geom_restore; } inline Client::MaximizeMode Client::maximizeMode() const { return max_mode; } inline bool Client::skipTaskbar( bool from_outside ) const { return from_outside ? original_skip_taskbar : skip_taskbar; } inline bool Client::skipPager() const { return skip_pager; } inline bool Client::keepAbove() const { return keep_above; } inline bool Client::keepBelow() const { return keep_below; } inline bool Client::storeSettings() const { return store_settings; } inline void Client::setStoreSettings( bool b ) { store_settings = b; } inline bool Client::shape() const { return is_shape; } inline bool Client::isFullScreen() const { return fullscreen_mode != FullScreenNone; } inline bool Client::isModal() const { return modal; } inline bool Client::hasNETSupport() const { return info->hasNETSupport(); } inline Colormap Client::colormap() const { return cmap; } inline pid_t Client::pid() const { return info->pid(); } inline void Client::invalidateLayer() { in_layer = UnknownLayer; } inline bool Client::isIconicState() const { return mapping_state == IconicState; } inline bool Client::isNormalState() const { return mapping_state == NormalState; } inline bool Client::isManaged() const { return mapping_state != WithdrawnState; } inline Time Client::userTime() const { assert( user_time != CurrentTime ); + assert( user_time != -1U ); return user_time; } inline QCString Client::windowRole() const { return window_role; } inline QRect Client::geometry() const { return frame_geometry; } inline QSize Client::size() const { return frame_geometry.size(); } inline QPoint Client::pos() const { return frame_geometry.topLeft(); } inline int Client::x() const { return frame_geometry.x(); } inline int Client::y() const { return frame_geometry.y(); } inline int Client::width() const { return frame_geometry.width(); } inline int Client::height() const { return frame_geometry.height(); } inline QRect Client::rect() const { return QRect( 0, 0, width(), height()); } inline QPoint Client::clientPos() const { return QPoint( border_left, border_top ); } inline QSize Client::clientSize() const { return client_size; } inline void Client::setGeometry( const QRect& r, ForceGeometry_t force ) { setGeometry( r.x(), r.y(), r.width(), r.height(), force ); } inline void Client::move( const QPoint & p, ForceGeometry_t force ) { move( p.x(), p.y(), force ); } inline void Client::plainResize( const QSize& s, ForceGeometry_t force ) { plainResize( s.width(), s.height(), force ); } inline void Client::resizeWithChecks( const QSize& s, ForceGeometry_t force ) { resizeWithChecks( s.width(), s.height(), force ); } inline bool Client::hasUserTimeSupport() const { return info->userTime() != -1U; } #ifdef NDEBUG kndbgstream& operator<<( kndbgstream& stream, const Client* ); #else kdbgstream& operator<<( kdbgstream& stream, const Client* ); #endif KWIN_COMPARE_PREDICATE( WindowMatchPredicate, Window, cl->window() == value ); KWIN_COMPARE_PREDICATE( FrameIdMatchPredicate, Window, cl->frameId() == value ); KWIN_COMPARE_PREDICATE( WrapperIdMatchPredicate, Window, cl->wrapperId() == value ); } // namespace #endif Index: trunk/kdebase/kwin/manage.cpp =================================================================== --- trunk/kdebase/kwin/manage.cpp (revision 255681) +++ trunk/kdebase/kwin/manage.cpp (revision 255682) @@ -1,536 +1,540 @@ /***************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 1999, 2000 Matthias Ettrich Copyright (C) 2003 Lubos Lunak You can Freely distribute this program under the GNU General Public License. See the file "COPYING" for the exact licensing terms. ******************************************************************/ /* This file contains things relevant to handling incoming events. */ #include "client.h" #include #include #include "notifications.h" extern Time qt_x_time; extern Atom qt_window_role; namespace KWinInternal { /*! Manages the clients. This means handling the very first maprequest: reparenting, initial geometry, initial state, placement, etc. Returns false if KWin is not going to manage this window. */ bool Client::manage( Window w, bool isMapped ) { XWindowAttributes attr; if( !XGetWindowAttributes(qt_xdisplay(), w, &attr)) return false; // initial state int init_mapping_state = NormalState; XWMHints * hints = XGetWMHints(qt_xdisplay(), w ); if (hints && (hints->flags & StateHint)) init_mapping_state = hints->initial_state; if (hints) XFree(hints); if( isMapped ) init_mapping_state = NormalState; // if it's already mapped, ignore hint if( init_mapping_state != NormalState && init_mapping_state != IconicState ) { // don't manage windows with strange initial mapping state // it's mapped and unmapped for WindowMaker applets // they usually map with initial_state == Withdrawn, // and don't want to be mapped // mapping it for a while will give the docking panel // a chance to get MapNotify for it, and swallow the matching // window // SELI XMapWindow( qt_xdisplay(), w ); XUnmapWindow( qt_xdisplay(), w ); return false; } // XGrabServer( qt_xdisplay()); // FRAME // from this place on, manage() mustn't return false block_geometry = 1; embedClient( w ); // SELI order all these things in some sane manner bool init_minimize = init_mapping_state == IconicState; unsigned long properties[ 2 ]; properties[ WinInfo::PROTOCOLS ] = NET::WMDesktop | NET::WMState | NET::WMWindowType | NET::WMStrut | NET::WMName | NET::WMIconGeometry | NET::WMIcon | NET::WMPid | NET::WMIconName | 0; properties[ WinInfo::PROTOCOLS2 ] = NET::WM2UserTime | NET::WM2StartupId | 0; info = new WinInfo( this, qt_xdisplay(), client, qt_xrootwin(), properties, 2 ); cmap = attr.colormap; bool mresize, mmove, mminimize, mmaximize, mclose; if( Motif::funcFlags( client, mresize, mmove, mminimize, mmaximize, mclose )) { motif_may_resize = mresize; // this should be set using minsize==maxsize, but oh well motif_may_move = mmove; // mminimize; - ignore, bogus - e.g. shading or sending to another desktop is "minimizing" too // mmaximize; - ignore, bogus - maximizing is basically just resizing motif_may_close = mclose; // motif apps like to crash when they set this hint and WM closes them anyway } XClassHint classHint; if ( XGetClassHint( qt_xdisplay(), client, &classHint ) ) { resource_name = classHint.res_name; resource_class = classHint.res_class; XFree( classHint.res_name ); XFree( classHint.res_class ); } detectNoBorder(); fetchName(); fetchIconicName(); getWMHints(); readTransient(); getIcons(); getWindowProtocols(); getWmNormalHints(); // get xSizeHint getWmClientLeader(); window_role = getStringProperty( w, qt_window_role ); // TODO try to obey all state information from info->state() original_skip_taskbar = skip_taskbar = ( info->state() & NET::SkipTaskbar) != 0; skip_pager = ( info->state() & NET::SkipPager) != 0; modal = ( info->state() & NET::Modal ) != 0; // window wants to stay on top? keep_above = ( info->state() & NET::KeepAbove ) != 0; // window wants to stay on bottom? keep_below = ( info->state() & NET::KeepBelow ) != 0; if( keep_above && keep_below ) keep_above = keep_below = false; KStartupInfoData asn_data; bool asn_valid = workspace()->checkStartupNotification( this, asn_data ); workspace()->updateClientLayer( this ); SessionInfo* session = workspace()->takeSessionInfo( this ); if ( session ) { if ( session->minimized ) init_minimize = true; if( session->userNoBorder ) setUserNoBorder( true ); } // initial desktop placement if ( info->desktop() ) desk = info->desktop(); // window had the initial desktop property! else if( asn_valid && asn_data.desktop() != 0 ) desk = asn_data.desktop(); if ( session ) { desk = session->desktop; if( session->onAllDesktops ) desk = NET::OnAllDesktops; } else if ( desk == 0 ) { // if this window is transient, ensure that it is opened on the // same window as its parent. this is necessary when an application // starts up on a different desktop than is currently displayed if( isTransient()) { ClientList mainclients = mainClients(); bool on_current = false; for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end(); ++it ) if( (*it)->isOnCurrentDesktop()) on_current = true; if( on_current ) desk = workspace()->currentDesktop(); else if( mainclients.count() > 0 ) desk = mainclients.first()->desktop(); } } if ( desk == 0 ) // assume window wants to be visible on the current desktop desk = workspace()->currentDesktop(); info->setDesktop( desk ); workspace()->updateOnAllDesktopsOfTransients( this ); // SELI // onAllDesktopsChange(); decoration doesn't exist here yet QRect geom( attr.x, attr.y, attr.width, attr.height ); bool placementDone = FALSE; if ( session ) geom = session->geometry; QRect area = workspace()->clientArea( geom.center(), desktop()); if (( geom.size() == workspace()->geometry().size()) // XINERAMA TODO check also size of the screen && noBorder() && !isUserNoBorder() && isFullScreenable()) { fullscreen_mode = FullScreenHack; // TODO XINERAMA show fullscreen on only one xinerama screen geom.moveTopLeft( QPoint( 0, 0 )); // in case they try to make it fullscreen, but misplace (#55290) placementDone = true; } if ( isDesktop() ) { // desktops are treated slightly special geom = workspace()->geometry(); placementDone = true; } if ( isMapped || session || placementDone || ( isTransient() && !isUtility() && !isDialog() && !isSplash())) { // TODO placementDone = TRUE; } else if( isTransient() && !hasNETSupport()) placementDone = true; else if( isDialog() && hasNETSupport()) // see Placement::placeDialog() ; // force using placement policy else if( isSplash()) ; // force using placement policy else { bool ignorePPosition = false; XClassHint classHint; // APICLEAN tohle je zduplikovane seshora if ( XGetClassHint(qt_xdisplay(), window(), &classHint) != 0 ) { if ( classHint.res_class ) ignorePPosition = ( options->ignorePositionClasses.find(QString::fromLatin1(classHint.res_class)) != options->ignorePositionClasses.end() ); XFree(classHint.res_name); XFree(classHint.res_class); } if ((xSizeHint.flags & PPosition) && ! ignorePPosition) { int tx = geom.x(); int ty = geom.y(); // TODO tyhle testy nepocitaji s dekoraci, ani s gravity if (tx < 0) tx = area.right() + tx; if (ty < 0) ty = area.bottom() + ty; geom.moveTopLeft(QPoint(tx, ty)); } if ( ( (xSizeHint.flags & PPosition) && !ignorePPosition ) || (xSizeHint.flags & USPosition) ) { placementDone = TRUE; } if ( (xSizeHint.flags & USSize) || (xSizeHint.flags & PSize) ) { // keep in mind that we now actually have a size :-) } } if (xSizeHint.flags & PMaxSize) geom.setSize( geom.size().boundedTo( QSize(xSizeHint.max_width, xSizeHint.max_height ) ) ); if (xSizeHint.flags & PMinSize) geom.setSize( geom.size().expandedTo( QSize(xSizeHint.min_width, xSizeHint.min_height ) ) ); if( isMovable()) { if( geom.x() > area.right() || geom.y() > area.bottom()) placementDone = FALSE; // weird, do not trust. } if ( placementDone ) move( geom.x(), geom.y() ); // before gravitating updateDecoration( false ); // also gravitates // TODO is CentralGravity right here, when resizing is done after gravitating? plainResize( sizeForClientSize( geom.size())); if( !placementDone ) { // placement needs to be after setting size workspace()->place( this ); placementDone = TRUE; } if (( !isSpecialWindow() || isToolbar()) && isMovable()) { if ( geometry().right() > area.right() && width() < area.width() ) move( area.right() - width(), y() ); if ( geometry().bottom() > area.bottom() && height() < area.height() ) move( x(), area.bottom() - height() ); if( !area.contains( geometry().topLeft() )) { int tx = x(); int ty = y(); if ( tx < area.x() ) tx = area.x(); if ( ty < area.y() ) ty = area.y(); move( tx, ty ); } } XShapeSelectInput( qt_xdisplay(), window(), ShapeNotifyMask ); if ( (is_shape = Shape::hasShape( window())) ) { updateShape(); } //CT extra check for stupid jdk 1.3.1. But should make sense in general // if client has initial state set to Iconic and is transient with a parent // window that is not Iconic, set init_state to Normal if( init_minimize && isTransient()) { ClientList mainclients = mainClients(); for( ClientList::ConstIterator it = mainclients.begin(); it != mainclients.end(); ++it ) if( (*it)->isShown()) init_minimize = false; // SELI even e.g. for NET::Utility? } if( init_minimize ) minimize(); // SELI this seems to be mainly for kstart and ksystraycmd // probably should be replaced by something better bool doNotShow = false; if ( workspace()->isNotManaged( caption() ) ) doNotShow = TRUE; if( isTopMenu()) doNotShow = true; // other settings from the previous session if ( session ) { setKeepAbove( session->keepAbove ); setKeepBelow( session->keepBelow ); setSkipTaskbar( session->skipTaskbar, true ); setSkipPager( session->skipPager ); setShade( session->shaded ? ShadeNormal : ShadeNone ); if( session->maximized != MaximizeRestore ) { maximize( (MaximizeMode) session->maximized ); geom_restore = session->restore; } if( session->fullscreen == FullScreenHack ) ; // nothing, this should be already set again above else if( session->fullscreen != FullScreenNone ) { setFullScreen( true, false ); geom_fs_restore = session->fsrestore; } } else { geom_restore = geometry(); // remember restore geometry if ( isMaximizable() && ( width() >= area.width() || height() >= area.height() ) ) { // window is too large for the screen, maximize in the // directions necessary if ( width() >= area.width() && height() >= area.height() ) { maximize( Client::MaximizeFull ); geom_restore = QRect(); // use placement when unmaximizing } else if ( width() >= area.width() ) { maximize( Client::MaximizeHorizontal ); geom_restore = QRect(); // use placement when unmaximizing geom_restore.setY( y()); // but only for horizontal direction geom_restore.setHeight( height()); } else if ( height() >= area.height() ) { maximize( Client::MaximizeVertical ); geom_restore = QRect(); // use placement when unmaximizing geom_restore.setX( x()); // but only for vertical direction geom_restore.setWidth( width()); } } // window may want to be maximized // done after checking that the window isn't larger than the workarea, so that // the restore geometry from the checks above takes precedence, and window // isn't restored larger than the workarea if ( (info->state() & NET::Max) == NET::Max ) maximize( Client::MaximizeFull ); else if ( info->state() & NET::MaxVert ) maximize( Client::MaximizeVertical ); else if ( info->state() & NET::MaxHoriz ) maximize( Client::MaximizeHorizontal ); if( fullscreen_mode != FullScreenHack ) { if(( info->state() & NET::FullScreen ) != 0 && isFullScreenable()) setFullScreen( true, false ); } } updateAllowedActions( true ); // TODO this should avoid flicker, because real restacking is done // only after manage() finishes, but the window is shown sooner // - keep it? XLowerWindow( qt_xdisplay(), frameId()); user_time = readUserTimeMapTimestamp( asn_valid ? &asn_data : NULL, session ); if ( isShown() && !doNotShow ) { if( isDialog()) Notify::raise( Notify::TransNew ); if( isNormalWindow()) Notify::raise( Notify::New ); // if session saving, force showing new windows (i.e. "save file?" dialogs etc.) if( workspace()->sessionSaving() && !isOnCurrentDesktop()) workspace()->setCurrentDesktop( desktop()); if( isOnCurrentDesktop()) { setMappingState( NormalState ); if( isMapped ) { workspace()->raiseClient( this ); rawShow(); } else { if( workspace()->allowClientActivation( this, user_time, false, session && session->active )) { workspace()->raiseClient( this ); rawShow(); if( !isSpecialWindow() || isOverride()) if ( options->focusPolicyIsReasonable() && wantsTabFocus() ) workspace()->requestFocus( this ); } else { workspace()->restackClientUnderActive( this ); rawShow(); if( !session && ( !isSpecialWindow() || isOverride())) demandAttention(); } } } else { virtualDesktopChange(); workspace()->raiseClient( this ); if( !session && !isMapped ) demandAttention(); } } else if( !doNotShow ) // !isShown() { rawHide(); setMappingState( IconicState ); } else // doNotShow { // SELI HACK !!! rawHide(); setMappingState( IconicState ); } assert( mappingState() != WithdrawnState ); if( isTopMenu()) hideClient( true ); - if( user_time == CurrentTime ) // no known user time, set something old + if( user_time == CurrentTime || user_time == -1U ) // no known user time, set something old + { user_time = qt_x_time - 1000000; + if( user_time == CurrentTime || user_time == -1U ) // let's be paranoid + user_time = qt_x_time - 1000000 + 10; + } updateWorkareaDiffs( area ); // sendSyntheticConfigureNotify(); done when setting mapping state delete session; // XUngrabServer( qt_xdisplay()); //FRAME return true; } // called only from manage() void Client::embedClient( Window w ) { assert( client == None ); assert( frame == None ); assert( wrapper == None ); client = w; // we don't want the window to be destroyed when we are destroyed XAddToSaveSet( qt_xdisplay(), client ); XSelectInput( qt_xdisplay(), client, NoEventMask ); XUnmapWindow( qt_xdisplay(), client ); XWindowChanges wc; // set the border width to 0 wc.border_width = 0; // TODO possibly save this, and also use it for initial configuring of the window XConfigureWindow( qt_xdisplay(), client, CWBorderWidth, &wc ); frame = XCreateSimpleWindow( qt_xdisplay(), qt_xrootwin(), 0, 0, 1, 1, 0, 0, 0 ); wrapper = XCreateSimpleWindow( qt_xdisplay(), frame, 0, 0, 1, 1, 0, 0, 0 ); XDefineCursor( qt_xdisplay(), frame, arrowCursor.handle()); // some apps are stupid and don't define their own cursor - set the arrow one for them XDefineCursor( qt_xdisplay(), wrapper, arrowCursor.handle()); XReparentWindow( qt_xdisplay(), client, wrapper, 0, 0 ); XSelectInput( qt_xdisplay(), frame, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | KeymapStateMask | ButtonMotionMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | ExposureMask | PropertyChangeMask | StructureNotifyMask | SubstructureRedirectMask | VisibilityChangeMask ); XSelectInput( qt_xdisplay(), wrapper, ClientWinMask | SubstructureNotifyMask ); XSelectInput( qt_xdisplay(), client, FocusChangeMask | PropertyChangeMask | ColormapChangeMask | EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask ); XSetWindowBackgroundPixmap( qt_xdisplay(), frameId(), None ); XSetWindowBackgroundPixmap( qt_xdisplay(), wrapperId(), None ); updateMouseGrab(); } } // namespace