interactive.c revision 705
0N/A/*
606N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0N/A *
0N/A * Permission is hereby granted, free of charge, to any person obtaining a
0N/A * copy of this software and associated documentation files (the
0N/A * "Software"), to deal in the Software without restriction, including
0N/A * without limitation the rights to use, copy, modify, merge, publish,
0N/A * distribute, and/or sell copies of the Software, and to permit persons
0N/A * to whom the Software is furnished to do so, provided that the above
0N/A * copyright notice(s) and this permission notice appear in all copies of
0N/A * the Software and that both the above copyright notice(s) and this
0N/A * permission notice appear in supporting documentation.
0N/A *
0N/A * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0N/A * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0N/A * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
0N/A * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
0N/A * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
0N/A * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
0N/A * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0N/A * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
0N/A * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0N/A *
0N/A * Except as contained in this notice, the name of a copyright holder
0N/A * shall not be used in advertising or otherwise to promote the sale, use
0N/A * or other dealings in this Software without prior written authorization
0N/A * of the copyright holder.
0N/A */
0N/A
705N/A#pragma ident "@(#)interactive.c 35.20 09/05/15 SMI"
0N/A
0N/A/************************************************************
0N/A Basic boilerplate extension.
0N/A
0N/A This file also contains the code to make the priocntl on behalf
0N/A of the clients.
0N/A
0N/A Note that ChangePriority also sets the last client with focus
0N/A to the normal priority.
0N/A
0N/A If there are knobs to be added to the system, for say the nice
0N/A values for the IA class, they would be added here.
0N/A********************************************************/
0N/A
0N/A/* THIS IS NOT AN X CONSORTIUM STANDARD */
0N/A
98N/A#ifdef HAVE_DIX_CONFIG_H
98N/A#include <dix-config.h>
98N/A#endif
98N/A
0N/A#include <errno.h>
0N/A#include <sys/types.h>
0N/A#include <stdio.h>
0N/A
0N/A#include <sys/priocntl.h>
0N/A#include <sys/iapriocntl.h>
0N/A#include <unistd.h>
0N/A
0N/A
0N/A#define NEED_REPLIES
0N/A#define NEED_EVENTS
0N/A#include <X11/X.h>
0N/A#include <X11/Xproto.h>
0N/A#include "os.h"
0N/A#include "dixstruct.h"
0N/A#include "windowstr.h"
0N/A#include "inputstr.h"
0N/A#include "extnsionst.h"
0N/A#define _XIA_SERVER_
0N/A#include <X11/extensions/interactive.h>
0N/A#include <X11/Xfuncproto.h>
0N/A#include "dix.h"
0N/A
0N/A#define UNSET_PRIORITY 0
0N/A#define SET_PRIORITY 1
0N/A#define SET_INTERACTIVE 2
0N/A
606N/Atypedef struct _ClientProcessInfo {
606N/A int count;
606N/A ConnectionPidPtr pids;
606N/A Bool boosted;
606N/A} ClientProcessRec, *ClientProcessPtr;
0N/A
606N/Atypedef struct {
606N/A ClientProcessPtr process; /* Process id information */
606N/A Bool wmgr;
606N/A} IAClientPrivateRec, *IAClientPrivatePtr;
0N/A
0N/Astatic int ProcIADispatch(ClientPtr client), SProcIADispatch(ClientPtr client);
0N/Astatic int ProcIASetProcessInfo(ClientPtr client), SProcIASetProcessInfo(ClientPtr client);
0N/Astatic int ProcIAGetProcessInfo(ClientPtr client), SProcIAGetProcessInfo(ClientPtr client);
0N/Astatic int ProcIAQueryVersion(ClientPtr client), SProcIAQueryVersion(ClientPtr client);
0N/Astatic void IACloseDown(ExtensionEntry *ext);
0N/Astatic void IAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata);
0N/A
0N/Astatic int InitializeClass(void );
0N/Astatic void SetIAPrivate(int*);
0N/Astatic void ChangeInteractive(ClientPtr);
606N/Astatic int SetPriority(const ClientProcessPtr, int);
0N/Astatic void ChangePriority(register ClientPtr client);
0N/A
0N/Astatic int SetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length);
606N/Astatic void FreeProcessList(IAClientPrivatePtr priv);
0N/A/* static int LocalConnection(OsCommPtr); */
0N/Astatic int PidSetEqual(ClientProcessPtr, ClientProcessPtr);
0N/A
0N/Astatic int IAWrapProcVectors(void);
0N/Astatic int IAUnwrapProcVectors(void);
0N/A
0N/Astatic CARD32 IAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg);
0N/A
0N/Astatic iaclass_t IAClass;
0N/Astatic id_t TScid;
0N/Astatic ClientProcessPtr LastPids = NULL;
0N/Astatic int ia_nice = IA_BOOST;
606N/Astatic Bool InteractiveOS = TRUE;
0N/Astatic unsigned long IAExtensionGeneration = 0;
0N/Astatic OsTimerPtr IAInitTimer = NULL;
0N/Astatic int (* IASavedProcVector[256]) (ClientPtr client);
0N/A
606N/Astatic int IAPrivKeyIndex;
606N/Astatic DevPrivateKey IAPrivKey = &IAPrivKeyIndex;
606N/A
606N/A#define GetIAClient(pClient) \
606N/A ((IAClientPrivatePtr) dixLookupPrivate(&(pClient)->devPrivates, IAPrivKey))
0N/A
606N/Astatic inline ClientProcessPtr
606N/AGetConnectionPids(ClientPtr pClient)
606N/A{
606N/A IAClientPrivatePtr priv = GetIAClient(pClient);
0N/A
606N/A if (priv == NULL) {
606N/A return NULL;
606N/A } else {
606N/A return priv->process;
606N/A }
606N/A}
0N/A
0N/A/* Set via xorg.conf option in loadable module */
0N/Aint IADebugLevel = 0;
0N/A
0N/A#define IA_DEBUG(level, func) \
0N/A if (IADebugLevel >= level) { func; } else (void)(0)
0N/A
0N/A#define IA_DEBUG_BASIC 1
0N/A#define IA_DEBUG_PRIOCNTL 3
0N/A
0N/Avoid
0N/AIAExtensionInit(void)
0N/A{
606N/A ConnectionPidRec myPid = P_MYID;
606N/A ClientProcessRec myProc = { 1, &myPid, FALSE };
606N/A
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO, "SolarisIA: Initializing (generation %ld)\n",
606N/A IAExtensionGeneration));
0N/A
0N/A if (IAExtensionGeneration == serverGeneration)
0N/A return;
0N/A
606N/A InteractiveOS = FALSE;
0N/A
0N/A if (InitializeClass() != Success)
0N/A return;
0N/A
606N/A if (SetPriority(&myProc, SET_INTERACTIVE) != Success)
0N/A return;
0N/A
606N/A if (SetPriority(&myProc, SET_PRIORITY) != Success)
0N/A return;
0N/A
0N/A if (!AddCallback(&ClientStateCallback, IAClientStateChange, NULL))
0N/A return;
0N/A
0N/A if (IAWrapProcVectors() != 0)
0N/A return;
0N/A
0N/A if (!AddExtension(IANAME, IANumberEvents, IANumberErrors,
606N/A ProcIADispatch, SProcIADispatch,
606N/A IACloseDown, StandardMinorOpcode))
0N/A return;
0N/A
0N/A /* InitExtensions is called before InitClientPrivates(serverClient)
0N/A so we set this timer to callback as soon as we hit WaitForSomething
0N/A to initialize the serverClient */
0N/A IAInitTimer = TimerSet(IAInitTimer, 0, 1, IAInitTimerCall, NULL);
0N/A
606N/A InteractiveOS = TRUE;
0N/A IAExtensionGeneration = serverGeneration;
0N/A
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: Finished initializing (generation %ld)\n",
606N/A IAExtensionGeneration));
606N/A}
606N/A
606N/A/* Allocate client private structure for this client */
606N/Astatic int
606N/AIAInitClientPrivate(ClientPtr pClient)
606N/A{
606N/A IAClientPrivatePtr priv;
606N/A
606N/A priv = GetIAClient(pClient);
606N/A if (priv != NULL) {
606N/A return Success;
606N/A }
606N/A
606N/A priv = xalloc(sizeof(IAClientPrivateRec));
606N/A if (priv == NULL) {
606N/A return BadAlloc;
606N/A }
606N/A
606N/A priv->process = NULL;
606N/A priv->wmgr = FALSE;
606N/A
606N/A dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, priv);
606N/A
606N/A return Success;
0N/A}
0N/A
0N/A/* Called when we first hit WaitForSomething to initialize serverClient */
0N/Astatic CARD32
0N/AIAInitTimerCall(OsTimerPtr timer,CARD32 now,pointer arg)
0N/A{
0N/A ConnectionPidRec serverPid;
0N/A
606N/A if (InteractiveOS != TRUE)
0N/A return 0;
0N/A
606N/A IAInitClientPrivate(serverClient);
0N/A
0N/A serverPid = getpid();
0N/A SetClientPrivate(serverClient, &serverPid, 1);
0N/A
0N/A ChangePriority(serverClient);
0N/A return 0;
0N/A}
0N/A
0N/A/* Called when new client connects or existing client disconnects */
0N/Astatic void
0N/AIAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer calldata)
0N/A{
0N/A NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
0N/A ClientPtr pClient = pci->client;
0N/A ClientProcessPtr CurrentPids;
606N/A IAClientPrivatePtr priv;
0N/A
0N/A switch (pClient->clientState) {
606N/A case ClientStateGone:
606N/A case ClientStateRetained:
606N/A priv = GetIAClient(pClient);
606N/A if (priv == NULL) {
606N/A return;
606N/A }
606N/A CurrentPids = priv->process;
0N/A
606N/A if (priv->wmgr) {
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: WindowManager closed (pid %d)\n",
606N/A (CurrentPids && CurrentPids->pids) ?
606N/A CurrentPids->pids[0] : -1));
0N/A }
0N/A
606N/A if (CurrentPids && CurrentPids->boosted) {
606N/A SetPriority(CurrentPids, UNSET_PRIORITY);
606N/A }
606N/A
606N/A if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
606N/A LastPids = NULL;
606N/A }
0N/A
606N/A FreeProcessList(priv);
606N/A xfree(priv);
606N/A dixSetPrivate(&(pClient)->devPrivates, IAPrivKey, NULL);
0N/A break;
606N/A
0N/A case ClientStateInitial:
606N/A IAInitClientPrivate(pClient);
0N/A break;
0N/A
0N/A default:
0N/A break;
0N/A }
0N/A}
0N/A
0N/A
0N/Astatic int
0N/AProcIADispatch (ClientPtr client)
0N/A{
0N/A REQUEST(xReq);
0N/A switch (stuff->data)
0N/A {
0N/A case X_IAQueryVersion:
0N/A return ProcIAQueryVersion(client);
0N/A case X_IASetProcessInfo:
0N/A return ProcIASetProcessInfo(client);
0N/A case X_IAGetProcessInfo:
0N/A return ProcIAGetProcessInfo(client);
0N/A default:
0N/A return BadRequest;
0N/A }
0N/A}
0N/A
0N/Astatic int
0N/AProcIAQueryVersion(ClientPtr client)
0N/A{
0N/A REQUEST(xIAQueryVersionReq);
0N/A xIAQueryVersionReply rep;
0N/A
0N/A REQUEST_SIZE_MATCH(xIAQueryVersionReq);
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
0N/A rep.majorVersion = IA_MAJOR_VERSION;
0N/A rep.minorVersion = IA_MINOR_VERSION;
0N/A WriteToClient(client, sizeof(xIAQueryVersionReply), (char *)&rep);
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic int
0N/AProcIASetProcessInfo(ClientPtr client)
0N/A{
0N/A
0N/A REQUEST(xIASetProcessInfoReq);
0N/A register int length;
183N/A static uid_t ServerUid = (uid_t)-1;
0N/A
0N/A REQUEST_AT_LEAST_SIZE(xIASetProcessInfoReq);
0N/A
183N/A if (ServerUid == (uid_t)-1)
0N/A ServerUid=getuid();
0N/A
0N/A if ((stuff->flags & INTERACTIVE_INFO) &&
0N/A (stuff->uid==ServerUid || ServerUid==0 || stuff->uid==0) &&
0N/A LocalClient(client)) {
606N/A length = stuff->length - (sizeof(xIASetProcessInfoReq)>>2);
0N/A SetClientPrivate(client, (ConnectionPidPtr)&stuff[1], length);
0N/A ChangeInteractive(client);
0N/A }
0N/A
0N/A if ((stuff->flags & INTERACTIVE_SETTING) &&
0N/A (stuff->uid==ServerUid || ServerUid==0) &&
0N/A LocalClient(client)) {
0N/A SetIAPrivate((int*)&stuff[1]);
0N/A }
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic int
0N/AProcIAGetProcessInfo(ClientPtr client)
0N/A{
606N/A IAClientPrivatePtr priv;
606N/A ClientProcessPtr CurrentPids;
0N/A REQUEST(xIAGetProcessInfoReq);
0N/A xIAGetProcessInfoReply rep;
606N/A register int length = 0;
606N/A caddr_t write_back = NULL;
0N/A
0N/A REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
0N/A rep.type = X_Reply;
0N/A rep.length = 0;
0N/A rep.sequenceNumber = client->sequence;
0N/A if (stuff->flags & INTERACTIVE_INFO) {
606N/A priv = GetIAClient(client);
606N/A if ( (priv == NULL) || (priv->process == NULL) ) {
606N/A rep.count = 0;
606N/A } else {
606N/A CurrentPids = priv->process;
606N/A rep.count = CurrentPids->count;
606N/A length = rep.count << 2;
606N/A write_back=(caddr_t)CurrentPids->pids;
606N/A }
0N/A }
0N/A if (stuff->flags & INTERACTIVE_SETTING) {
0N/A rep.count=1;
0N/A length=rep.count << 2;
0N/A write_back=(caddr_t)&ia_nice;
0N/A }
0N/A
0N/A WriteToClient(client, sizeof(xIAGetProcessInfoReply), (char *)&rep);
0N/A WriteToClient(client, length, write_back);
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic void
0N/AIACloseDown(ExtensionEntry *ext)
0N/A{
606N/A InteractiveOS = FALSE;
0N/A
0N/A IAUnwrapProcVectors();
0N/A
0N/A DeleteCallback(&ClientStateCallback, IAClientStateChange, NULL);
0N/A}
0N/A
0N/A/*
0N/A The SProc* functions are here for completeness. They should never get
0N/A called. But since they do the server has to eat the request and
0N/A return thanks for sharing.
0N/A*/
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIADispatch (ClientPtr client)
0N/A{
0N/A REQUEST(xReq);
0N/A switch (stuff->data)
0N/A {
0N/A case X_IAQueryVersion:
0N/A return SProcIAQueryVersion(client);
0N/A case X_IASetProcessInfo:
0N/A return SProcIASetProcessInfo(client);
0N/A case X_IAGetProcessInfo:
0N/A return SProcIAGetProcessInfo(client);
0N/A default:
0N/A return BadRequest;
0N/A }
0N/A}
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIAQueryVersion(ClientPtr client)
0N/A{
0N/A REQUEST_SIZE_MATCH(xIAQueryVersionReq);
0N/A return (client->noClientException);
0N/A}
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIASetProcessInfo(ClientPtr client)
0N/A{
0N/A REQUEST(xIASetProcessInfoReq);
0N/A REQUEST_AT_LEAST_SIZE(xIASetProcessInfoReq);
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/A/*ARGSUSED*/
0N/Astatic int
0N/ASProcIAGetProcessInfo(ClientPtr client)
0N/A{
0N/A REQUEST(xIAGetProcessInfoReq);
0N/A REQUEST_SIZE_MATCH(xIAGetProcessInfoReq);
0N/A
0N/A return (client->noClientException);
0N/A}
0N/A
0N/Astatic void
0N/AChangeInteractive(ClientPtr client)
0N/A{
606N/A ClientProcessPtr CurrentPids = GetConnectionPids(client);
0N/A
606N/A if (InteractiveOS==FALSE)
0N/A return;
0N/A
606N/A if (!CurrentPids || !CurrentPids->pids)
0N/A return;
0N/A
606N/A SetPriority(CurrentPids, SET_INTERACTIVE);
0N/A}
0N/A
0N/A/*
606N/A * Loop through pids associated with client. Magically make last focus
606N/A * group go non-interactive -IA_BOOST.
606N/A */
0N/Astatic void
0N/AChangePriority(register ClientPtr client)
0N/A{
606N/A IAClientPrivatePtr priv = GetIAClient(client);
606N/A ClientProcessPtr CurrentPids = (priv == NULL ? NULL : priv->process);
0N/A
606N/A if (CurrentPids && LastPids && PidSetEqual(CurrentPids, LastPids)) {
606N/A /* Shortcut. Focus changed between two windows with same pid */
0N/A return;
606N/A }
0N/A
606N/A /* Remove priority boost for last focus group */
606N/A if (LastPids) {
606N/A SetPriority(LastPids, UNSET_PRIORITY);
606N/A LastPids = NULL;
606N/A }
606N/A
606N/A /* If no pid info for current client, then we're done here.
606N/A * This can happen if we have a remote client with focus or if the client
606N/A * is statically linked or if it is using a down rev version of libX11.
606N/A */
606N/A if ( (CurrentPids == NULL) || (CurrentPids->count == 0) ||
606N/A (CurrentPids->pids == NULL) ) {
606N/A return;
606N/A }
0N/A
606N/A /* Set the priority boost if it isn't already active */
606N/A if (!CurrentPids->boosted) {
606N/A SetPriority(CurrentPids, SET_PRIORITY);
606N/A }
606N/A
606N/A /* Make sure server or wmgr isn't unset by testing for them, so
606N/A * that LastPids is never set to point to the server or wmgr pid.
606N/A */
606N/A if ((client->index != serverClient->index) && (priv->wmgr != TRUE)) {
606N/A LastPids = CurrentPids;
606N/A }
0N/A}
0N/A
0N/Astatic int
0N/AInitializeClass(void)
0N/A{
606N/A pcinfo_t pcinfo;
0N/A
606N/A /* Get TS class information */
606N/A strcpy (pcinfo.pc_clname, "TS");
606N/A priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo);
606N/A TScid = pcinfo.pc_cid;
0N/A
606N/A /* Get IA class information */
606N/A strcpy (pcinfo.pc_clname, "IA");
606N/A if ((priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo)) == -1)
0N/A return ~Success;
0N/A
606N/A IAClass.pc_cid = pcinfo.pc_cid;
606N/A ((iaparms_t*)IAClass.pc_clparms)->ia_uprilim = IA_NOCHANGE;
606N/A ((iaparms_t*)IAClass.pc_clparms)->ia_upri = IA_NOCHANGE;
0N/A
606N/A return Success;
0N/A}
0N/A
0N/Astatic int
606N/ASetPriority(const ClientProcessPtr cpp, int cmd)
0N/A{
606N/A pcparms_t pcinfo;
606N/A long ret = Success;
0N/A gid_t usr_egid = getegid();
606N/A int i;
0N/A
606N/A if ( (cpp == NULL) || (cpp->pids == NULL) || (cpp->count == 0) ) {
606N/A return Success;
606N/A }
606N/A
606N/A if ( setegid(0) < 0 ) {
0N/A Error("Error in setting egid to 0");
0N/A }
0N/A
606N/A for (i = 0; i < cpp->count ; i++) {
606N/A id_t pid = cpp->pids[i];
0N/A
606N/A pcinfo.pc_cid=PC_CLNULL;
606N/A if ((priocntl(P_PID, pid, PC_GETPARMS, (caddr_t)&pcinfo)) < 0) {
606N/A if ( setegid(usr_egid) < 0 ) {
606N/A Error("Error in resetting egid");
606N/A }
606N/A return ~Success; /* Scary time; punt */
606N/A }
606N/A
606N/A /* If process is in TS or IA class we can safely set parameters */
606N/A if ((pcinfo.pc_cid == IAClass.pc_cid) || (pcinfo.pc_cid == TScid)) {
606N/A
606N/A switch (cmd) {
606N/A case UNSET_PRIORITY:
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
0N/A break;
606N/A case SET_PRIORITY:
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_SET_INTERACTIVE;
0N/A break;
606N/A case SET_INTERACTIVE:
606N/A /* If this returns true, the process is already in the */
606N/A /* IA class, so we don't need to update it. */
606N/A if ( pcinfo.pc_cid == IAClass.pc_cid)
606N/A continue;
0N/A
0N/A ((iaparms_t*)IAClass.pc_clparms)->ia_mode=IA_INTERACTIVE_OFF;
0N/A break;
606N/A }
0N/A
606N/A if (priocntl(P_PID, pid, PC_SETPARMS, (caddr_t)&IAClass) == -1)
0N/A {
606N/A ret = ~Success;
0N/A }
0N/A
606N/A IA_DEBUG(IA_DEBUG_PRIOCNTL,
606N/A {
606N/A const char *cmdmsg;
0N/A
606N/A switch (cmd) {
606N/A case UNSET_PRIORITY: cmdmsg = "UNSET_PRIORITY"; break;
606N/A case SET_PRIORITY: cmdmsg = "SET_PRIORITY"; break;
606N/A case SET_INTERACTIVE: cmdmsg = "SET_INTERACTIVE"; break;
606N/A default: cmdmsg = "UNKNOWN_CMD!!!"; break;
606N/A }
606N/A LogMessage(X_INFO, "SolarisIA: SetPriority(%ld, %s): %s\n",
606N/A pid, cmdmsg,
606N/A (ret == Success) ? "succeeeded" : "failed");
606N/A });
606N/A }
0N/A }
0N/A
606N/A if (setegid(usr_egid) < 0)
606N/A Error("Error in resetting egid");
606N/A
606N/A if (ret == Success) {
606N/A if (cmd == SET_PRIORITY) {
606N/A cpp->boosted = TRUE;
606N/A } else if (cmd == UNSET_PRIORITY) {
606N/A cpp->boosted = FALSE;
606N/A }
606N/A }
606N/A
606N/A return ret;
0N/A}
0N/A
0N/Astatic void
0N/ASetIAPrivate(int * value)
0N/A{
606N/A ia_nice = *value;
0N/A}
0N/A
0N/A/*****************************************************************************
0N/A * Various utility functions - in Xsun these lived in Xserver/os/process.c
0N/A */
0N/A
0N/A/* In Xsun we used the osPrivate in OsCommPtr, so this was SetOsPrivate. */
0N/Astatic int
0N/ASetClientPrivate(ClientPtr client, ConnectionPidPtr stuff, int length)
606N/A{
0N/A ClientProcessPtr cpp;
606N/A IAClientPrivatePtr priv;
0N/A
606N/A priv = GetIAClient(client);
606N/A if (priv == NULL) {
606N/A IAInitClientPrivate(client);
606N/A } else {
606N/A FreeProcessList(priv);
606N/A }
606N/A
0N/A cpp = (ClientProcessPtr)xalloc(sizeof(ClientProcessRec));
0N/A
0N/A if (cpp == NULL)
0N/A return BadAlloc;
0N/A
0N/A cpp->pids = (ConnectionPidPtr)xalloc(sizeof(ConnectionPidRec)*length);
0N/A
0N/A if (cpp->pids == NULL) {
0N/A xfree(cpp);
0N/A return BadAlloc;
0N/A }
0N/A
0N/A cpp->count = length;
0N/A memcpy(cpp->pids, stuff, sizeof(ConnectionPidRec)*length);
606N/A cpp->boosted = FALSE;
606N/A
606N/A priv->process = cpp;
0N/A return Success;
0N/A}
0N/A
0N/Astatic void
606N/AFreeProcessList(IAClientPrivatePtr priv)
0N/A{
606N/A ClientProcessPtr cpp = priv->process;
606N/A
0N/A if (cpp == NULL)
0N/A return;
606N/A priv->process = NULL;
0N/A
0N/A if ( LastPids == cpp )
0N/A LastPids = NULL;
0N/A
0N/A if (cpp->pids != NULL)
0N/A xfree(cpp->pids);
0N/A
0N/A xfree(cpp);
0N/A}
0N/A
0N/A/*
606N/A Check to see that all in current (a) are in last (b).
606N/A And that a and b have the same number of members in the set.
0N/A*/
606N/Astatic int
0N/APidSetEqual(ClientProcessPtr a, ClientProcessPtr b)
0N/A{
606N/A int aN, bN;
606N/A int count = a->count;
606N/A int retval = 1;
0N/A
606N/A if (a->count != b->count) {
606N/A return 0; /* definately NOT the same set */
606N/A }
0N/A
606N/A for (aN = 0; aN < count; aN++) {
606N/A retval = 0;
606N/A for (bN = 0; bN < count ; bN++) {
606N/A if (a->pids[aN] == b->pids[bN]) {
606N/A retval = 1;
606N/A break;
606N/A }
606N/A }
606N/A if (retval == 0)
606N/A return retval;
606N/A }
0N/A
606N/A return retval;
0N/A}
0N/A
0N/A
0N/A/*****************************************************************************
0N/A * Wrappers for normal procs - in Xsun we modified the original procs directly
0N/A * in dix, but here we wrap them for a small performance loss but a large
0N/A * increase in maintainability and ease of porting to new releases.
0N/A */
0N/A
0N/Astatic int
0N/AIAProcSetInputFocus(ClientPtr client)
0N/A{
0N/A int res;
0N/A Window focusID;
606N/A WindowPtr focusWin;
0N/A REQUEST(xSetInputFocusReq);
0N/A
0N/A res = (*IASavedProcVector[X_SetInputFocus])(client);
606N/A if ((res != Success) || (InteractiveOS != TRUE))
0N/A return res;
0N/A
0N/A focusID = stuff->focus;
0N/A
98N/A switch (focusID) {
98N/A case None:
98N/A focusWin = NullWindow;
98N/A break;
98N/A case PointerRoot:
98N/A focusWin = PointerRootWin;
98N/A break;
98N/A default:
606N/A res = dixLookupWindow(&focusWin, focusID, client, DixReadAccess);
606N/A if (res != Success)
606N/A return res;
0N/A }
0N/A
0N/A if ((focusWin != NullWindow) && (focusWin != PointerRootWin)) {
606N/A register ClientPtr requestee = wClient(focusWin);
606N/A ChangePriority(requestee);
0N/A }
0N/A
0N/A return res;
0N/A}
0N/A
0N/Astatic int
0N/AIAProcSendEvent(ClientPtr client)
0N/A{
0N/A int res;
0N/A REQUEST(xSendEventReq);
0N/A
0N/A res = (*IASavedProcVector[X_SendEvent])(client);
606N/A if ((res != Success) || (InteractiveOS != TRUE))
0N/A return res;
0N/A
606N/A if ((InteractiveOS==TRUE) &&
606N/A (GetIAClient(client)->wmgr == TRUE) &&
0N/A (stuff->event.u.u.type == ClientMessage) &&
0N/A (stuff->event.u.u.detail == 32) ) {
0N/A
0N/A register ClientPtr requestee;
606N/A WindowPtr pWin = NULL;
705N/A DeviceIntPtr pPtr = PickPointer(client);
0N/A
0N/A if (stuff->destination == PointerWindow)
705N/A pWin = GetSpriteWindow(pPtr);
0N/A else if (stuff->destination == InputFocus)
0N/A {
0N/A WindowPtr inputFocus = inputInfo.keyboard->focus->win;
0N/A
0N/A if (inputFocus == NoneWin)
0N/A return Success;
0N/A
0N/A /* If the input focus is PointerRootWin, send the event to where
0N/A the pointer is if possible, then perhaps propogate up to root. */
0N/A if (inputFocus == PointerRootWin)
705N/A inputFocus = GetCurrentRootWindow(pPtr);
0N/A
705N/A if (IsParent(inputFocus, GetSpriteWindow(pPtr)))
705N/A pWin = GetSpriteWindow(pPtr);
0N/A else
0N/A pWin = inputFocus;
0N/A }
0N/A else
606N/A {
606N/A res = dixLookupWindow(&pWin, stuff->destination, client,
606N/A DixReadAccess);
606N/A if (res != Success)
606N/A return res;
606N/A }
606N/A
606N/A
0N/A if (!pWin)
0N/A return BadWindow;
0N/A
606N/A requestee = wClient(pWin);
606N/A ChangePriority(requestee);
0N/A }
0N/A return res;
0N/A}
0N/A
0N/Astatic Bool
0N/AIAProcChangeWindowAttributes(ClientPtr client)
0N/A{
0N/A REQUEST(xChangeWindowAttributesReq);
0N/A
606N/A if ((InteractiveOS==TRUE) && (stuff->valueMask & CWEventMask) &&
606N/A (GetIAClient(client)->wmgr == FALSE) ) {
0N/A
0N/A register XID *pVlist = (XID *) &stuff[1];
0N/A register Mask tmask = stuff->valueMask;
98N/A register Mask index2 = 0;
0N/A
0N/A while (tmask) {
0N/A index2 = (Mask) lowbit (tmask);
0N/A tmask &= ~index2;
0N/A if (index2 == CWEventMask) {
0N/A break;
0N/A }
0N/A pVlist++;
0N/A }
0N/A
0N/A if ((index2 == CWEventMask) && (*pVlist & SubstructureRedirectMask)) {
0N/A IA_DEBUG(IA_DEBUG_BASIC,
606N/A ClientProcessPtr CurrentPids=GetConnectionPids(client);
0N/A
606N/A LogMessage(X_INFO,
606N/A "SolarisIA: WindowManager detected (pid %d)\n",
606N/A (CurrentPids && CurrentPids->pids) ?
606N/A CurrentPids->pids[0] : -1));
0N/A
606N/A GetIAClient(client)->wmgr = TRUE;
0N/A ChangePriority(client);
606N/A LastPids = NULL;
0N/A }
0N/A }
0N/A
0N/A return (*IASavedProcVector[X_ChangeWindowAttributes])(client);
0N/A}
0N/A
0N/A
0N/Astatic int
0N/AIAWrapProcVectors(void)
0N/A{
0N/A IASavedProcVector[X_SetInputFocus] = ProcVector[X_SetInputFocus];
0N/A ProcVector[X_SetInputFocus] = IAProcSetInputFocus;
0N/A
0N/A IASavedProcVector[X_SendEvent] = ProcVector[X_SendEvent];
0N/A ProcVector[X_SendEvent] = IAProcSendEvent;
0N/A
0N/A IASavedProcVector[X_ChangeWindowAttributes]
0N/A = ProcVector[X_ChangeWindowAttributes];
0N/A ProcVector[X_ChangeWindowAttributes] = IAProcChangeWindowAttributes;
0N/A
0N/A return 0;
0N/A}
0N/A
0N/Astatic int
0N/AIAUnwrapProcVectors(void)
0N/A{
0N/A ProcVector[X_SetInputFocus] = IASavedProcVector[X_SetInputFocus];
0N/A ProcVector[X_SendEvent] = IASavedProcVector[X_SendEvent];
0N/A ProcVector[X_ChangeWindowAttributes] = IASavedProcVector[X_ChangeWindowAttributes];
0N/A
0N/A return 0;
0N/A}
0N/A
0N/A