open-src/xserver/xorg/sun-src/IA/interactive.c
changeset 606 068c11b419c9
parent 436 4c79f0dc36ed
child 705 24ca414edbff
equal deleted inserted replaced
605:e5259db5befc 606:068c11b419c9
     1 /*
     1 /*
     2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     3  *
     3  *
     4  * Permission is hereby granted, free of charge, to any person obtaining a
     4  * Permission is hereby granted, free of charge, to any person obtaining a
     5  * copy of this software and associated documentation files (the
     5  * copy of this software and associated documentation files (the
     6  * "Software"), to deal in the Software without restriction, including
     6  * "Software"), to deal in the Software without restriction, including
     7  * without limitation the rights to use, copy, modify, merge, publish,
     7  * without limitation the rights to use, copy, modify, merge, publish,
    25  * shall not be used in advertising or otherwise to promote the sale, use
    25  * shall not be used in advertising or otherwise to promote the sale, use
    26  * or other dealings in this Software without prior written authorization
    26  * or other dealings in this Software without prior written authorization
    27  * of the copyright holder.
    27  * of the copyright holder.
    28  */
    28  */
    29 
    29 
    30 #pragma ident   "@(#)interactive.c 35.18     08/06/16 SMI"
    30 #pragma ident   "@(#)interactive.c 35.19     09/01/14 SMI"
    31 
    31 
    32 /************************************************************
    32 /************************************************************
    33 	Basic boilerplate extension.
    33 	Basic boilerplate extension.
    34 
    34 
    35 	This file also contains the code to make the priocntl on behalf
    35 	This file also contains the code to make the priocntl on behalf
    73 
    73 
    74 #define UNSET_PRIORITY 		0
    74 #define UNSET_PRIORITY 		0
    75 #define SET_PRIORITY		1
    75 #define SET_PRIORITY		1
    76 #define SET_INTERACTIVE 	2
    76 #define SET_INTERACTIVE 	2
    77 
    77 
    78 #define SERVER			0x1
       
    79 #define WMGR			0x2
       
    80 #define BOTH			0x3
       
    81 
       
    82 typedef struct _ClientProcessInfo {
    78 typedef struct _ClientProcessInfo {
    83 	int count;
    79     int 		count;
    84 	ConnectionPidPtr pids;
    80     ConnectionPidPtr	pids;
    85 } ClientProcessRec, * ClientProcessPtr;
    81     Bool		boosted;
       
    82 } ClientProcessRec, *ClientProcessPtr;
       
    83 
       
    84 typedef struct {
       
    85     ClientProcessPtr    process; /* Process id information */    
       
    86     Bool		wmgr;
       
    87 } IAClientPrivateRec, *IAClientPrivatePtr;
    86 
    88 
    87 static int ProcIADispatch(ClientPtr client), SProcIADispatch(ClientPtr client);
    89 static int ProcIADispatch(ClientPtr client), SProcIADispatch(ClientPtr client);
    88 static int ProcIASetProcessInfo(ClientPtr client), SProcIASetProcessInfo(ClientPtr client);
    90 static int ProcIASetProcessInfo(ClientPtr client), SProcIASetProcessInfo(ClientPtr client);
    89 static int ProcIAGetProcessInfo(ClientPtr client), SProcIAGetProcessInfo(ClientPtr client);
    91 static int ProcIAGetProcessInfo(ClientPtr client), SProcIAGetProcessInfo(ClientPtr client);
    90 static int ProcIAQueryVersion(ClientPtr client), SProcIAQueryVersion(ClientPtr client);
    92 static int ProcIAQueryVersion(ClientPtr client), SProcIAQueryVersion(ClientPtr client);
    92 static void IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata);
    94 static void IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata);
    93 
    95 
    94 static int InitializeClass(void );
    96 static int InitializeClass(void );
    95 static void SetIAPrivate(int*);
    97 static void SetIAPrivate(int*);
    96 static void ChangeInteractive(ClientPtr);
    98 static void ChangeInteractive(ClientPtr);
    97 static int SetPriority(int, int);
    99 static int SetPriority(const ClientProcessPtr, int);
    98 static void UnsetLastPriority(ClientProcessPtr LastPid); 
       
    99 static void ChangePriority(register ClientPtr client);
   100 static void ChangePriority(register ClientPtr client);
   100 
   101 
   101 static int SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length);
   102 static int SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length);
   102 static void FreeProcessList(ClientPtr client);
   103 static void FreeProcessList(IAClientPrivatePtr priv);
   103 /* static int LocalConnection(OsCommPtr); */
   104 /* static int LocalConnection(OsCommPtr); */
   104 static int PidSetEqual(ClientProcessPtr, ClientProcessPtr);
   105 static int PidSetEqual(ClientProcessPtr, ClientProcessPtr);
   105 
   106 
   106 static int IAWrapProcVectors(void);
   107 static int IAWrapProcVectors(void);
   107 static int IAUnwrapProcVectors(void);
   108 static int IAUnwrapProcVectors(void);
   109 static CARD32 IAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg);
   110 static CARD32 IAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg);
   110 
   111 
   111 static iaclass_t 	IAClass;
   112 static iaclass_t 	IAClass;
   112 static id_t		TScid;
   113 static id_t		TScid;
   113 static ClientProcessPtr	LastPids = NULL;
   114 static ClientProcessPtr	LastPids = NULL;
   114 static int 		specialIAset = 0;
       
   115 static int 		ia_nice = IA_BOOST;
   115 static int 		ia_nice = IA_BOOST;
   116 static Bool 		InteractiveOS = xTrue;
   116 static Bool 		InteractiveOS = TRUE;
   117 static ClientPtr 	wmClientptr = NULL;
       
   118 static unsigned long 	IAExtensionGeneration = 0;
   117 static unsigned long 	IAExtensionGeneration = 0;
   119 static OsTimerPtr 	IAInitTimer = NULL;
   118 static OsTimerPtr 	IAInitTimer = NULL;
   120 static int (* IASavedProcVector[256]) (ClientPtr client);
   119 static int (* IASavedProcVector[256]) (ClientPtr client);
   121 
   120 
   122 typedef struct {
   121 static int IAPrivKeyIndex;
   123     ClientProcessPtr    process; /* Process id information */    
   122 static DevPrivateKey IAPrivKey = &IAPrivKeyIndex;
   124     Bool		wmgr;
   123 
   125 } IAClientPrivateRec, *IAClientPrivatePtr;
   124 #define GetIAClient(pClient)	\
   126 
   125     ((IAClientPrivatePtr) dixLookupPrivate(&(pClient)->devPrivates, IAPrivKey))
   127 static int	IAClientPrivateIndex;
   126 
   128 
   127 static inline ClientProcessPtr
   129 #define GetIAClient(pClient)    ((IAClientPrivatePtr) (pClient)->devPrivates[IAClientPrivateIndex].ptr)
   128 GetConnectionPids(ClientPtr pClient)
   130 #define GetConnectionPids(pClient)	(GetIAClient(pClient)->process)
   129 {
       
   130     IAClientPrivatePtr priv = GetIAClient(pClient);
       
   131 
       
   132     if (priv == NULL) {
       
   133 	return NULL;
       
   134     } else {
       
   135 	return priv->process;
       
   136     }
       
   137 }
   131 
   138 
   132 /* Set via xorg.conf option in loadable module */
   139 /* Set via xorg.conf option in loadable module */
   133 int IADebugLevel = 0;
   140 int IADebugLevel = 0;
   134 
   141 
   135 #define IA_DEBUG(level, func)	\
   142 #define IA_DEBUG(level, func)	\
   139 #define IA_DEBUG_PRIOCNTL	3
   146 #define IA_DEBUG_PRIOCNTL	3
   140 
   147 
   141 void
   148 void
   142 IAExtensionInit(void)
   149 IAExtensionInit(void)
   143 {
   150 {
       
   151     ConnectionPidRec	myPid = P_MYID;
       
   152     ClientProcessRec	myProc = { 1, &myPid, FALSE };
       
   153     
   144     IA_DEBUG(IA_DEBUG_BASIC, 
   154     IA_DEBUG(IA_DEBUG_BASIC, 
   145       LogMessage(X_INFO, "SolarisIA: Initializing (generation %ld)\n",
   155 	     LogMessage(X_INFO, "SolarisIA: Initializing (generation %ld)\n",
   146 	IAExtensionGeneration));
   156 			IAExtensionGeneration));
   147 
   157 
   148     if (IAExtensionGeneration == serverGeneration)
   158     if (IAExtensionGeneration == serverGeneration)
   149 	return;
   159 	return;
   150 
   160 
   151     InteractiveOS=xFalse;
   161     InteractiveOS = FALSE;
   152 
   162 
   153     if (InitializeClass() != Success)
   163     if (InitializeClass() != Success)
   154 	return;
   164 	return;
   155 
   165 
   156     if (SetPriority(P_MYID, SET_INTERACTIVE) != Success)
   166     if (SetPriority(&myProc, SET_INTERACTIVE) != Success)
   157 	return;
   167 	return;
   158 
   168 
   159     if (SetPriority(P_MYID, SET_PRIORITY) != Success)
   169     if (SetPriority(&myProc, SET_PRIORITY) != Success)
   160 	return;
   170 	return;
   161 
       
   162     IAClientPrivateIndex = AllocateClientPrivateIndex();
       
   163     if (IAClientPrivateIndex < 0)
       
   164 	return;
       
   165     if (!AllocateClientPrivate (IAClientPrivateIndex,
       
   166 				      sizeof (IAClientPrivateRec)))
       
   167         return;
       
   168 
   171 
   169     if (!AddCallback(&ClientStateCallback, IAClientStateChange, NULL))
   172     if (!AddCallback(&ClientStateCallback, IAClientStateChange, NULL))
   170         return;
   173         return;
   171 
   174 
   172     if (IAWrapProcVectors() != 0)
   175     if (IAWrapProcVectors() != 0)
   173 	return;
   176 	return;
   174 
   177 
   175     if (!AddExtension(IANAME, IANumberEvents, IANumberErrors,
   178     if (!AddExtension(IANAME, IANumberEvents, IANumberErrors,
   176 				 ProcIADispatch, SProcIADispatch,
   179 		      ProcIADispatch, SProcIADispatch,
   177 				 IACloseDown, StandardMinorOpcode))
   180 		      IACloseDown, StandardMinorOpcode))
   178 	return;
   181 	return;
   179 
   182 
   180     /* InitExtensions is called before InitClientPrivates(serverClient)
   183     /* InitExtensions is called before InitClientPrivates(serverClient)
   181        so we set this timer to callback as soon as we hit WaitForSomething
   184        so we set this timer to callback as soon as we hit WaitForSomething
   182        to initialize the serverClient */
   185        to initialize the serverClient */
   183     IAInitTimer = TimerSet(IAInitTimer, 0, 1, IAInitTimerCall, NULL);
   186     IAInitTimer = TimerSet(IAInitTimer, 0, 1, IAInitTimerCall, NULL);
   184 
   187 
   185     specialIAset = 0;
   188     InteractiveOS = TRUE;
   186     InteractiveOS = xTrue;
       
   187     IAExtensionGeneration = serverGeneration;
   189     IAExtensionGeneration = serverGeneration;
   188 
   190 
   189     IA_DEBUG(IA_DEBUG_BASIC, 
   191     IA_DEBUG(IA_DEBUG_BASIC, 
   190       LogMessage(X_INFO, "SolarisIA: Finished initializing (generation %ld)\n",
   192 	     LogMessage(X_INFO,
   191 	IAExtensionGeneration));
   193 			"SolarisIA: Finished initializing (generation %ld)\n",
       
   194 			IAExtensionGeneration));
       
   195 }
       
   196 
       
   197 /* Allocate client private structure for this client */
       
   198 static int
       
   199 IAInitClientPrivate(ClientPtr pClient)
       
   200 {
       
   201     IAClientPrivatePtr priv;
       
   202 
       
   203     priv = GetIAClient(pClient);
       
   204     if (priv != NULL) {
       
   205 	return Success;
       
   206     }
       
   207 	
       
   208     priv = xalloc(sizeof(IAClientPrivateRec));
       
   209     if (priv == NULL) {
       
   210 	return BadAlloc;
       
   211     }
       
   212 
       
   213     priv->process = NULL;
       
   214     priv->wmgr = FALSE;
       
   215     
       
   216     dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, priv);
       
   217 
       
   218     return Success;
   192 }
   219 }
   193 
   220 
   194 /* Called when we first hit WaitForSomething to initialize serverClient */
   221 /* Called when we first hit WaitForSomething to initialize serverClient */
   195 static CARD32 
   222 static CARD32 
   196 IAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg)
   223 IAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg)
   197 {
   224 {
   198     ConnectionPidRec serverPid;
   225     ConnectionPidRec serverPid;
   199 
   226 
   200     if (InteractiveOS != xTrue)
   227     if (InteractiveOS != TRUE)
   201 	return 0;
   228 	return 0;
   202 
   229 
   203     GetConnectionPids(serverClient) = NULL;
   230     IAInitClientPrivate(serverClient);
   204     GetIAClient(serverClient)->wmgr = FALSE;
       
   205 
   231 
   206     serverPid = getpid();
   232     serverPid = getpid();
   207     SetClientPrivate(serverClient, &serverPid, 1);
   233     SetClientPrivate(serverClient, &serverPid, 1);
   208 
   234 
   209     ChangePriority(serverClient);
   235     ChangePriority(serverClient);
   215 IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
   241 IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
   216 {
   242 {
   217     NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
   243     NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
   218     ClientPtr pClient = pci->client;
   244     ClientPtr pClient = pci->client;
   219     ClientProcessPtr CurrentPids;
   245     ClientProcessPtr CurrentPids;
       
   246     IAClientPrivatePtr priv;
   220 
   247 
   221     switch (pClient->clientState) {
   248     switch (pClient->clientState) {
   222     case ClientStateGone:
   249       case ClientStateGone:
   223     case ClientStateRetained:
   250       case ClientStateRetained:
   224 	CurrentPids = GetConnectionPids(pClient);
   251 	priv = GetIAClient(pClient);
   225 
   252 	if (priv == NULL) {
   226 	if (pClient==wmClientptr) {
   253 	    return;
       
   254 	}
       
   255 	CurrentPids = priv->process;
       
   256 
       
   257 	if (priv->wmgr) {
   227 	    IA_DEBUG(IA_DEBUG_BASIC,
   258 	    IA_DEBUG(IA_DEBUG_BASIC,
   228 	      LogMessage(X_INFO, "SolarisIA: WindowManager closed (pid %d)\n",
   259 		     LogMessage(X_INFO,
   229 	      (CurrentPids && CurrentPids->pids) ? CurrentPids->pids[0] : -1));
   260 				"SolarisIA: WindowManager closed (pid %d)\n",
   230 	    wmClientptr=NULL;
   261 				(CurrentPids && CurrentPids->pids) ?
   231 	}
   262 				 CurrentPids->pids[0] : -1));
   232 
   263 	}
   233 	if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids))
   264 
   234 	    LastPids=NULL;
   265 	if (CurrentPids && CurrentPids->boosted) {
   235 
   266 	    SetPriority(CurrentPids, UNSET_PRIORITY);
   236 	FreeProcessList(pClient);
   267 	}
   237 	GetIAClient(pClient)->wmgr = FALSE;
   268 	
       
   269 	if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
       
   270 	    LastPids = NULL;
       
   271 	}
       
   272 
       
   273 	FreeProcessList(priv);
       
   274 	xfree(priv);
       
   275 	dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, NULL);
   238 	break;
   276 	break;
   239 	
   277 
   240     case ClientStateInitial:
   278     case ClientStateInitial:
   241 	GetConnectionPids(pClient) = NULL;
   279 	IAInitClientPrivate(pClient);
   242 	GetIAClient(pClient)->wmgr = FALSE;
       
   243 	break;
   280 	break;
   244 
   281 
   245     default:
   282     default:
   246 	break;
   283 	break;
   247     }
   284     }
   295 	ServerUid=getuid();
   332 	ServerUid=getuid();
   296 
   333 
   297     if ((stuff->flags & INTERACTIVE_INFO) && 
   334     if ((stuff->flags & INTERACTIVE_INFO) && 
   298 	(stuff->uid==ServerUid || ServerUid==0 || stuff->uid==0) &&
   335 	(stuff->uid==ServerUid || ServerUid==0 || stuff->uid==0) &&
   299 	LocalClient(client)) {
   336 	LocalClient(client)) {
   300 	length=stuff->length-(sizeof(xIASetProcessInfoReq)>>2);
   337 	length = stuff->length - (sizeof(xIASetProcessInfoReq)>>2);
   301 	SetClientPrivate(client, (ConnectionPidPtr)&stuff[1], length);
   338 	SetClientPrivate(client, (ConnectionPidPtr)&stuff[1], length);
   302 	ChangeInteractive(client);
   339 	ChangeInteractive(client);
   303     }
   340     }
   304 
   341 
   305     if ((stuff->flags & INTERACTIVE_SETTING) && 
   342     if ((stuff->flags & INTERACTIVE_SETTING) && 
   312 }
   349 }
   313 
   350 
   314 static int
   351 static int
   315 ProcIAGetProcessInfo(ClientPtr client)
   352 ProcIAGetProcessInfo(ClientPtr client)
   316 {
   353 {
   317     ClientProcessPtr CurrentPids=GetConnectionPids(client);
   354     IAClientPrivatePtr	priv;
       
   355     ClientProcessPtr CurrentPids;
   318     REQUEST(xIAGetProcessInfoReq);
   356     REQUEST(xIAGetProcessInfoReq);
   319     xIAGetProcessInfoReply rep;
   357     xIAGetProcessInfoReply rep;
   320     register int length=0;
   358     register int length = 0;
   321     caddr_t write_back=NULL;
   359     caddr_t write_back = NULL;
   322 
   360 
   323     REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
   361     REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
   324     rep.type = X_Reply;
   362     rep.type = X_Reply;
   325     rep.length = 0;
   363     rep.length = 0;
   326     rep.sequenceNumber = client->sequence;
   364     rep.sequenceNumber = client->sequence;
   327     if (stuff->flags & INTERACTIVE_INFO) {
   365     if (stuff->flags & INTERACTIVE_INFO) {
   328 	    if (!CurrentPids) 
   366 	priv = GetIAClient(client);
   329     		rep.count = 0;
   367 	if ( (priv == NULL) || (priv->process == NULL) ) {
   330 	    else {
   368 	    rep.count = 0;
   331     		rep.count = CurrentPids->count;
   369 	} else {
   332        		length = rep.count << 2;
   370     	    CurrentPids = priv->process;
   333 	        write_back=(caddr_t)CurrentPids->pids;
   371 	    rep.count = CurrentPids->count;
   334 	    }
   372 	    length = rep.count << 2;
       
   373 	    write_back=(caddr_t)CurrentPids->pids;
       
   374 	}
   335     }
   375     }
   336     if (stuff->flags & INTERACTIVE_SETTING) {
   376     if (stuff->flags & INTERACTIVE_SETTING) {
   337 	rep.count=1;
   377 	rep.count=1;
   338 	length=rep.count << 2;
   378 	length=rep.count << 2;
   339 	write_back=(caddr_t)&ia_nice;
   379 	write_back=(caddr_t)&ia_nice;
   345 }
   385 }
   346 
   386 
   347 static void
   387 static void
   348 IACloseDown(ExtensionEntry *ext)
   388 IACloseDown(ExtensionEntry *ext)
   349 {
   389 {
   350     InteractiveOS=xFalse;
   390     InteractiveOS = FALSE;
   351 
   391 
   352     IAUnwrapProcVectors();
   392     IAUnwrapProcVectors();
   353 
   393 
   354     DeleteCallback(&ClientStateCallback, IAClientStateChange, NULL);
   394     DeleteCallback(&ClientStateCallback, IAClientStateChange, NULL);
   355 }
   395 }
   407 }
   447 }
   408 
   448 
   409 static void
   449 static void
   410 ChangeInteractive(ClientPtr client)
   450 ChangeInteractive(ClientPtr client)
   411 {
   451 {
   412    ClientProcessPtr CurrentPids=GetConnectionPids(client);
   452     ClientProcessPtr CurrentPids = GetConnectionPids(client);
   413    register int count;
   453 
   414 
   454     if (InteractiveOS==FALSE)
   415    if (InteractiveOS==xFalse)
       
   416         return;
   455         return;
   417 
   456 
   418    if (!CurrentPids || !CurrentPids->pids)
   457     if (!CurrentPids || !CurrentPids->pids)
   419 	return;
   458 	return;
   420 
   459 
   421    count=CurrentPids->count;
   460     SetPriority(CurrentPids, SET_INTERACTIVE);
   422 
       
   423    while(count--)
       
   424       SetPriority(CurrentPids->pids[count], SET_INTERACTIVE);
       
   425 }
   461 }
   426 
   462 
   427 /*
   463 /*
   428 Loop through pids associated with client. Magically make last focus
   464  * Loop through pids associated with client. Magically make last focus
   429 group go non-interactive -IA_BOOST.
   465  * group go non-interactive -IA_BOOST.
   430 */
   466  */
   431 static void
   467 static void
   432 ChangePriority(register ClientPtr client)
   468 ChangePriority(register ClientPtr client)
   433 {
   469 {
   434    ClientProcessPtr CurrentPids=GetConnectionPids(client);
   470     IAClientPrivatePtr priv = GetIAClient(client);
   435    register int count;
   471     ClientProcessPtr CurrentPids = (priv == NULL ? NULL : priv->process);
   436 
   472 
   437    /* If no pid info for current client make sure to unset last focus group. */
   473     if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
   438    /* This can happen if we have a remote client with focus or if the client */
   474 	/* Shortcut. Focus changed between two windows with same pid */
   439    /* is statically linked or if it is using a down rev version of libX11.   */
   475 	return;
   440    if (!CurrentPids || !CurrentPids->pids) {
   476     }
   441 	if (LastPids && LastPids->pids) {
   477 
   442 	    UnsetLastPriority(LastPids);
   478     /* Remove priority boost for last focus group */
   443 	    LastPids=NULL;
   479     if (LastPids) {
   444 	}
   480 	SetPriority(LastPids, UNSET_PRIORITY);
   445 	return;
   481 	LastPids = NULL;
   446    }
   482     }
   447 
   483     
   448    /* Make sure server or wmgr isn't unset by testing for them */
   484     /* If no pid info for current client, then we're done here.
   449    /* this way LastPids is never set to point to the server or */
   485      * This can happen if we have a remote client with focus or if the client
   450    /* wmgr pid.						       */
   486      * is statically linked or if it is using a down rev version of libX11.
   451    if ((client->index==serverClient->index || 
   487      */
   452      GetIAClient(client)->wmgr==xTrue)) {
   488     if ( (CurrentPids == NULL) || (CurrentPids->count == 0) ||
   453 
   489 	 (CurrentPids->pids == NULL) ) {
   454        if ((specialIAset < BOTH) && CurrentPids->pids) {
   490 	return;
   455 
   491     }
   456 	   if (client->index == serverClient->index) {
   492 
   457 	       specialIAset |= SERVER;	
   493     /* Set the priority boost if it isn't already active */
   458 	   }
   494     if (!CurrentPids->boosted) {
   459 	   else {
   495 	SetPriority(CurrentPids, SET_PRIORITY);
   460 	       specialIAset |= WMGR; 
   496     }
   461 	   }
   497     
   462 	   SetPriority(CurrentPids->pids[0], SET_PRIORITY);
   498     /* Make sure server or wmgr isn't unset by testing for them, so
   463        }
   499      * that LastPids is never set to point to the server or wmgr pid.
   464        return;
   500      */
   465    }
   501     if ((client->index != serverClient->index) && (priv->wmgr != TRUE)) {
   466 
   502 	LastPids = CurrentPids;
   467    if (LastPids && LastPids->pids) {
   503     }
   468 	if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids))
       
   469 		return;				/*Shortcut. Focus changed
       
   470 						  between two windows with
       
   471 						  same pid */
       
   472 	UnsetLastPriority(LastPids);
       
   473    }
       
   474   
       
   475    count=CurrentPids->count;
       
   476    while(count--)
       
   477       SetPriority(CurrentPids->pids[count], SET_PRIORITY);
       
   478    LastPids=CurrentPids;
       
   479 }
       
   480 
       
   481 static void
       
   482 UnsetLastPriority(ClientProcessPtr LastPids)
       
   483 {
       
   484     register int LastPidcount=LastPids->count;
       
   485 
       
   486     while(LastPidcount--)
       
   487       	SetPriority(LastPids->pids[LastPidcount], UNSET_PRIORITY);
       
   488 }
   504 }
   489 
   505 
   490 static int
   506 static int
   491 InitializeClass(void)
   507 InitializeClass(void)
   492 {
   508 {
   493    pcinfo_t  pcinfo;
   509     pcinfo_t  pcinfo;
   494 
   510 
   495    /* Get TS class information 					*/ 
   511     /* Get TS class information */
   496 
   512     strcpy (pcinfo.pc_clname, "TS");
   497    strcpy (pcinfo.pc_clname, "TS");
   513     priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo); 
   498    priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo); 
   514     TScid = pcinfo.pc_cid;
   499    TScid=pcinfo.pc_cid;
   515 
   500 
   516     /* Get IA class information */
   501    /* Get IA class information */
   517     strcpy (pcinfo.pc_clname, "IA");
   502    strcpy (pcinfo.pc_clname, "IA");
   518     if ((priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo)) == -1)
   503    if ((priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo)) == -1)
       
   504         return ~Success;
   519         return ~Success;
   505  
   520  
   506    IAClass.pc_cid=pcinfo.pc_cid;
   521     IAClass.pc_cid = pcinfo.pc_cid;
   507    ((iaparms_t*)IAClass.pc_clparms)->ia_uprilim=IA_NOCHANGE;
   522     ((iaparms_t*)IAClass.pc_clparms)->ia_uprilim = IA_NOCHANGE;
   508    ((iaparms_t*)IAClass.pc_clparms)->ia_upri=IA_NOCHANGE;
   523     ((iaparms_t*)IAClass.pc_clparms)->ia_upri = IA_NOCHANGE;
   509 
   524 
   510    return Success;
   525     return Success;
   511 }
   526 }
   512 
   527 
   513 static int
   528 static int
   514 SetPriority(int pid, int cmd)
   529 SetPriority(const ClientProcessPtr cpp, int cmd)
   515 {
   530 {
   516     pcparms_t pcinfo;
   531     pcparms_t 	pcinfo;
   517     long	ret;
   532     long	ret = Success;
   518     gid_t	usr_egid = getegid();
   533     gid_t	usr_egid = getegid();
   519 
   534     int		i;
   520     if ( setegid(0) < 0 )
   535 
       
   536     if ( (cpp == NULL) || (cpp->pids == NULL) || (cpp->count == 0) ) {
       
   537 	return Success;
       
   538     }
       
   539     
       
   540     if ( setegid(0) < 0 ) {
   521 	Error("Error in setting egid to 0");
   541 	Error("Error in setting egid to 0");
   522 
   542     }
   523 
   543 
   524     pcinfo.pc_cid=PC_CLNULL;
   544     for (i = 0; i < cpp->count ; i++) {
   525     if ((priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcinfo)) < 0) {
   545 	id_t	pid = cpp->pids[i];
   526 	if ( setegid(usr_egid) < 0 )
   546 
   527 	    Error("Error in resetting egid");
   547 	pcinfo.pc_cid=PC_CLNULL;
   528 
   548 	if ((priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcinfo)) < 0) {
   529 	return ~Success; /* Scary time; punt */
   549 	    if ( setegid(usr_egid) < 0 ) {
   530     }
   550 		Error("Error in resetting egid");
   531 
   551 	    }
   532     /* If process is in TS or IA class we can safely set parameters */
   552 	    return ~Success; /* Scary time; punt */
   533     if ((pcinfo.pc_cid == IAClass.pc_cid) || (pcinfo.pc_cid == TScid)) {
   553 	}
   534 
   554 
   535        switch (cmd) {
   555 	/* If process is in TS or IA class we can safely set parameters */
   536        case UNSET_PRIORITY:
   556 	if ((pcinfo.pc_cid == IAClass.pc_cid) || (pcinfo.pc_cid == TScid)) {
       
   557 
       
   558 	    switch (cmd) {
       
   559 	      case UNSET_PRIORITY:
   537    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
   560    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
   538 		break;
   561 		break;
   539        case SET_PRIORITY:
   562 	      case SET_PRIORITY:
   540    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_SET_INTERACTIVE;
   563    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_SET_INTERACTIVE;
   541 		break;
   564 		break;
   542        case SET_INTERACTIVE: 
   565 	      case SET_INTERACTIVE: 
   543       /* If this returns true, the process is already in the IA class */
   566 		/* If this returns true, the process is already in the 	*/
   544       /* So just return.						   */
   567 		/* IA class, so we don't need to update it.		*/
   545 		 if ( pcinfo.pc_cid == IAClass.pc_cid)
   568 		if ( pcinfo.pc_cid == IAClass.pc_cid)
   546 			return Success;
   569 		    continue;
   547 
   570 
   548    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
   571    		((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
   549 		break;
   572 		break;
   550        }
   573 	    }
   551 
   574 
   552 	if ( priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&IAClass) == -1 )
   575 	    if (priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&IAClass) == -1)
   553 	    {
   576 	    {
   554 	    ret = ~Success;
   577 		ret = ~Success;
   555 	    }
   578 	    }
   556 	else
   579 
       
   580 	    IA_DEBUG(IA_DEBUG_PRIOCNTL,
   557 	    {
   581 	    {
   558 	    ret = Success;
   582 		const char *cmdmsg;
   559 	    }
   583 
   560 
   584 		switch (cmd) {
   561 
   585 		  case UNSET_PRIORITY:	cmdmsg = "UNSET_PRIORITY";	break;
   562 	IA_DEBUG(IA_DEBUG_PRIOCNTL,
   586 		  case SET_PRIORITY:	cmdmsg = "SET_PRIORITY"; 	break;
   563 	{
   587 		  case SET_INTERACTIVE:	cmdmsg = "SET_INTERACTIVE"; 	break;
   564 	    const char *cmdmsg;
   588 		  default:		cmdmsg = "UNKNOWN_CMD!!!"; 	break;
   565 
   589 		}
   566 	    switch (cmd) {
   590 		LogMessage(X_INFO, "SolarisIA: SetPriority(%ld, %s): %s\n", 
   567 	    case UNSET_PRIORITY:   cmdmsg = "UNSET_PRIORITY"; break;
   591 			   pid, cmdmsg,
   568 	    case SET_PRIORITY:     cmdmsg = "SET_PRIORITY"; break;
   592 			   (ret == Success) ? "succeeeded" : "failed");
   569 	    case SET_INTERACTIVE:  cmdmsg = "SET_INTERACTIVE"; break;
   593 	    });
   570 	    default:		   cmdmsg = "UNKNOWN_CMD!!!"; break;
   594 	}
   571 	    }
   595     }
   572 	    LogMessage(X_INFO, "SolarisIA: SetPriority(%d, %s): %s\n", 
   596 
   573 	      pid, cmdmsg, (ret == Success) ? "succeeeded" : "failed");
   597     if (setegid(usr_egid) < 0)
   574 	});
   598 	Error("Error in resetting egid");
   575 
   599 
   576 
   600     if (ret == Success) {
   577 	if ( setegid(usr_egid) < 0 )
   601 	if (cmd == SET_PRIORITY) {
   578 	    Error("Error in resetting egid");
   602 	    cpp->boosted = TRUE;
   579 
   603 	} else if (cmd == UNSET_PRIORITY) {
   580 	return ret;
   604 	    cpp->boosted = FALSE;
   581     }
   605 	}
   582 
   606     }
   583     return ~Success;
   607     
       
   608     return ret;
   584 }
   609 }
   585 
   610 
   586 static void
   611 static void
   587 SetIAPrivate(int * value)
   612 SetIAPrivate(int * value)
   588 {
   613 {
   589 	ia_nice=*value;
   614     ia_nice = *value;
   590 }
   615 }
   591 
   616 
   592 /*****************************************************************************
   617 /*****************************************************************************
   593  * Various utility functions - in Xsun these lived in Xserver/os/process.c
   618  * Various utility functions - in Xsun these lived in Xserver/os/process.c
   594  */
   619  */
   595 
   620 
   596 /* In Xsun we used the osPrivate in OsCommPtr, so this was SetOsPrivate. */
   621 /* In Xsun we used the osPrivate in OsCommPtr, so this was SetOsPrivate. */
   597 static int
   622 static int
   598 SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length)
   623 SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length)
   599 {	
   624 {
   600     ClientProcessPtr	cpp;
   625     ClientProcessPtr	cpp;
   601 
   626     IAClientPrivatePtr priv;
   602     FreeProcessList(client);
   627 
   603 	
   628     priv = GetIAClient(client);
       
   629     if (priv == NULL) {
       
   630 	IAInitClientPrivate(client);
       
   631     } else {
       
   632 	FreeProcessList(priv);
       
   633     }
       
   634 
   604     cpp = (ClientProcessPtr)xalloc(sizeof(ClientProcessRec));
   635     cpp = (ClientProcessPtr)xalloc(sizeof(ClientProcessRec));
   605 
   636 
   606     if (cpp == NULL)
   637     if (cpp == NULL)
   607 	return BadAlloc;
   638 	return BadAlloc;
   608 
   639 
   611     if (cpp->pids == NULL) {
   642     if (cpp->pids == NULL) {
   612 	xfree(cpp);
   643 	xfree(cpp);
   613 	return BadAlloc;
   644 	return BadAlloc;
   614     }
   645     }
   615 
   646 
   616     GetConnectionPids(client) = cpp;
       
   617     cpp->count = length;
   647     cpp->count = length;
   618     memcpy(cpp->pids, stuff, sizeof(ConnectionPidRec)*length);
   648     memcpy(cpp->pids, stuff, sizeof(ConnectionPidRec)*length);
   619     
   649     cpp->boosted = FALSE;
       
   650 
       
   651     priv->process = cpp;
   620     return Success;
   652     return Success;
   621 }
   653 }
   622 
   654 
   623 static void
   655 static void
   624 FreeProcessList(ClientPtr client)
   656 FreeProcessList(IAClientPrivatePtr priv)
   625 {
   657 {
   626     ClientProcessPtr	cpp = GetConnectionPids(client);
   658     ClientProcessPtr	cpp = priv->process;
   627     
   659 
   628     if (cpp == NULL)
   660     if (cpp == NULL)
   629 	return;
   661 	return;
       
   662     priv->process = NULL;
   630 
   663 
   631     if ( LastPids == cpp )
   664     if ( LastPids == cpp )
   632 	LastPids = NULL;
   665 	LastPids = NULL;
   633 
   666 
   634     if (cpp->pids != NULL)
   667     if (cpp->pids != NULL)
   635 	xfree(cpp->pids);
   668 	xfree(cpp->pids);
   636 
   669 
   637     xfree(cpp);
   670     xfree(cpp);
   638 
       
   639     GetConnectionPids(client) = NULL;
       
   640 }
   671 }
   641 
   672 
   642 /*
   673 /*
   643         Check to see that all in current (a) are in
   674   Check to see that all in current (a) are in last (b).
   644         last (b). And that a and b have the same number
   675   And that a and b have the same number of members in the set.
   645         of members in the set.
       
   646 */
   676 */
   647 int
   677 static int
   648 PidSetEqual(ClientProcessPtr a, ClientProcessPtr b)
   678 PidSetEqual(ClientProcessPtr a, ClientProcessPtr b)
   649 {
   679 {
   650         register int currentcount=a->count;
   680     int aN, bN;
   651         register int lastcount=b->count;
   681     int count = a->count;
   652         int retval;
   682     int retval = 1;
   653 
   683 
   654         if (currentcount != lastcount)  
   684     if (a->count != b->count) {
   655                 return 0; /* definately NOT the same set */
   685 	return 0; /* definately NOT the same set */
   656 
   686     }
   657         while(currentcount--) {
   687 
   658             retval=0;
   688     for (aN = 0; aN < count; aN++) {
   659             while(lastcount--)
   689 	retval = 0;
   660                 if (a->pids[currentcount]==b->pids[lastcount]) {
   690 	for (bN = 0; bN < count ; bN++) {
   661                         retval=1;
   691 	    if (a->pids[aN] == b->pids[bN]) {
   662                         break;
   692 		retval = 1;
   663                 }
   693 		break;
   664             if (retval==0)
   694 	    }
   665                 return retval;
   695 	}
   666             lastcount=b->count;
   696 	if (retval == 0)
   667         }
   697 	    return retval;
   668 
   698     }
   669         return retval;
   699 
       
   700     return retval;
   670 }
   701 }
   671 
   702 
   672 
   703 
   673 /*****************************************************************************
   704 /*****************************************************************************
   674  * Wrappers for normal procs - in Xsun we modified the original procs directly
   705  * Wrappers for normal procs - in Xsun we modified the original procs directly
   679 static int
   710 static int
   680 IAProcSetInputFocus(ClientPtr client)
   711 IAProcSetInputFocus(ClientPtr client)
   681 {
   712 {
   682     int res;
   713     int res;
   683     Window focusID;
   714     Window focusID;
   684     register WindowPtr focusWin;
   715     WindowPtr focusWin;
   685     REQUEST(xSetInputFocusReq);
   716     REQUEST(xSetInputFocusReq);
   686 
   717 
   687     res = (*IASavedProcVector[X_SetInputFocus])(client);
   718     res = (*IASavedProcVector[X_SetInputFocus])(client);
   688     if ((res != Success) || (InteractiveOS != xTrue))
   719     if ((res != Success) || (InteractiveOS != TRUE))
   689 	return res;
   720 	return res;
   690 
   721 
   691     focusID = stuff->focus;
   722     focusID = stuff->focus;
   692 
   723 
   693     switch (focusID) {
   724     switch (focusID) {
   696 	break;
   727 	break;
   697       case PointerRoot:
   728       case PointerRoot:
   698 	focusWin = PointerRootWin;
   729 	focusWin = PointerRootWin;
   699 	break;
   730 	break;
   700       default:
   731       default:
   701 	if (!(focusWin = SecurityLookupWindow(focusID, client,
   732 	res = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
   702                                                SecurityReadAccess)))
   733 	if (res != Success)
   703 	    return BadWindow;
   734 	    return res;
   704     }
   735     }
   705 
   736 
   706     if ((focusWin != NullWindow) && (focusWin != PointerRootWin)) {
   737     if ((focusWin != NullWindow) && (focusWin != PointerRootWin)) {
   707 	register ClientPtr requestee;
   738 	register ClientPtr requestee = wClient(focusWin);
   708         ClientProcessPtr wmPid=NULL;
   739 	ChangePriority(requestee);
   709         ClientProcessPtr RequesteePids=NULL;
       
   710  
       
   711         if (wmClientptr)
       
   712                 wmPid=GetConnectionPids(wmClientptr);
       
   713  
       
   714         requestee=wClient(focusWin);
       
   715         RequesteePids=GetConnectionPids(requestee);
       
   716  
       
   717         /* if wm is not setting focus to himself */
       
   718  
       
   719         if (wmPid && RequesteePids && !PidSetEqual(wmPid, RequesteePids))
       
   720             ChangePriority(requestee);
       
   721         else  {
       
   722  
       
   723             /* If wm is setting focus to himself and Lastpids exists and
       
   724                LastPids pids are valid Unset the priority for the LastPids
       
   725                focus group */
       
   726  
       
   727             if (wmPid && RequesteePids && PidSetEqual(wmPid, RequesteePids))
       
   728                 if (LastPids && LastPids->pids) {
       
   729                     UnsetLastPriority(LastPids);
       
   730                     LastPids=NULL;
       
   731                 }
       
   732         }
       
   733     }
   740     }
   734 
   741 
   735     return res;
   742     return res;
   736 }
   743 }
   737 
   744 
   740 {
   747 {
   741     int res;
   748     int res;
   742     REQUEST(xSendEventReq);
   749     REQUEST(xSendEventReq);
   743 
   750 
   744     res = (*IASavedProcVector[X_SendEvent])(client);
   751     res = (*IASavedProcVector[X_SendEvent])(client);
   745     if ((res != Success) || (InteractiveOS != xTrue))
   752     if ((res != Success) || (InteractiveOS != TRUE))
   746 	return res;
   753 	return res;
   747 
   754 
   748     if ((InteractiveOS==xTrue) &&
   755     if ((InteractiveOS==TRUE) &&
   749         (client == wmClientptr) &&
   756         (GetIAClient(client)->wmgr == TRUE) &&
   750         (stuff->event.u.u.type == ClientMessage) &&
   757         (stuff->event.u.u.type == ClientMessage) &&
   751         (stuff->event.u.u.detail == 32) ) {
   758         (stuff->event.u.u.detail == 32) ) {
   752  
   759  
   753         register ClientPtr requestee;
   760         register ClientPtr requestee;
   754         ClientProcessPtr wmPid=NULL;
   761 	WindowPtr pWin = NULL;
   755         ClientProcessPtr RequesteePids=NULL;
       
   756 	WindowPtr pWin;
       
   757 
   762 
   758 	if (stuff->destination == PointerWindow)
   763 	if (stuff->destination == PointerWindow)
   759 	    pWin = GetSpriteWindow();
   764 	    pWin = GetSpriteWindow();
   760 	else if (stuff->destination == InputFocus)
   765 	else if (stuff->destination == InputFocus)
   761 	{
   766 	{
   773 		pWin = GetSpriteWindow();
   778 		pWin = GetSpriteWindow();
   774 	    else
   779 	    else
   775 		pWin = inputFocus;
   780 		pWin = inputFocus;
   776 	}
   781 	}
   777 	else
   782 	else
   778 	    pWin = SecurityLookupWindow(stuff->destination, client,
   783 	{
   779 	    				SecurityReadAccess);
   784 	    res = dixLookupWindow(&pWin, stuff->destination, client,
       
   785 				  DixReadAccess);
       
   786 	    if (res != Success)
       
   787 		return res;
       
   788 	}
       
   789 
       
   790 	    
   780 	if (!pWin)
   791 	if (!pWin)
   781 	    return BadWindow;
   792 	    return BadWindow;
   782  
   793  
   783         if (wmClientptr)
   794         requestee = wClient(pWin);
   784 	    wmPid=GetConnectionPids(wmClientptr);
   795 	ChangePriority(requestee);
   785         requestee=wClient(pWin);
       
   786         RequesteePids=GetConnectionPids(requestee);
       
   787  
       
   788         /* if wm is not setting focus to himself */
       
   789         if (wmPid && RequesteePids && !PidSetEqual(wmPid, RequesteePids)) {
       
   790             ChangePriority(requestee);
       
   791 	}
       
   792 	else {
       
   793  
       
   794             /* If wm is setting focus to himself and Lastpids exists and
       
   795                LastPids pids are valid Unset the priority for the LastPids
       
   796                focus group */
       
   797  
       
   798                 if (LastPids && LastPids->pids) {
       
   799                     UnsetLastPriority(LastPids);
       
   800                     LastPids=NULL;
       
   801                 }
       
   802         }
       
   803     }
   796     }
   804     return res;
   797     return res;
   805 }
   798 }
   806 
   799 
   807 static Bool
   800 static Bool
   808 IAProcChangeWindowAttributes(ClientPtr client)
   801 IAProcChangeWindowAttributes(ClientPtr client)
   809 {
   802 {
   810     REQUEST(xChangeWindowAttributesReq);
   803     REQUEST(xChangeWindowAttributesReq);
   811 
   804 
   812     if ((InteractiveOS==xTrue) && (stuff->valueMask & CWEventMask) &&
   805     if ((InteractiveOS==TRUE) && (stuff->valueMask & CWEventMask) &&
   813 	(GetIAClient(client)->wmgr == xFalse) ) {
   806 	(GetIAClient(client)->wmgr == FALSE) ) {
   814 
   807 
   815 	register XID *pVlist = (XID *) &stuff[1];
   808 	register XID *pVlist = (XID *) &stuff[1];
   816 	register Mask tmask = stuff->valueMask;
   809 	register Mask tmask = stuff->valueMask;
   817 	register Mask index2 = 0;
   810 	register Mask index2 = 0;
   818 
   811 
   825 	    pVlist++;
   818 	    pVlist++;
   826 	}
   819 	}
   827 
   820 
   828 	if ((index2 == CWEventMask) && (*pVlist & SubstructureRedirectMask)) {
   821 	if ((index2 == CWEventMask) && (*pVlist & SubstructureRedirectMask)) {
   829 	    IA_DEBUG(IA_DEBUG_BASIC,
   822 	    IA_DEBUG(IA_DEBUG_BASIC,
   830 	    ClientProcessPtr CurrentPids=GetConnectionPids(client);
   823 		     ClientProcessPtr CurrentPids=GetConnectionPids(client);
   831 
   824 
   832 	    LogMessage(X_INFO, "SolarisIA: WindowManager detected (pid %d)\n",
   825 		     LogMessage(X_INFO,
   833 	      (CurrentPids && CurrentPids->pids) ? CurrentPids->pids[0] : -1));
   826 				"SolarisIA: WindowManager detected (pid %d)\n",
   834 
   827 				(CurrentPids && CurrentPids->pids) ?
   835 
   828 				 CurrentPids->pids[0] : -1));
   836 	    GetIAClient(client)->wmgr=xTrue;
   829 
   837 	    wmClientptr = client;
   830 	    GetIAClient(client)->wmgr = TRUE;
   838 	    ChangePriority(client);
   831 	    ChangePriority(client);
       
   832 	    LastPids = NULL;
   839 	}
   833 	}
   840     }
   834     }
   841 
   835 
   842     return (*IASavedProcVector[X_ChangeWindowAttributes])(client);
   836     return (*IASavedProcVector[X_ChangeWindowAttributes])(client);
   843 }
   837 }