summaryrefslogtreecommitdiff
path: root/randr/rrmode.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@guitar.keithp.com>2007-02-18 23:49:38 -0800
committerKeith Packard <keithp@neko.keithp.com>2007-03-17 23:20:07 -0700
commit2c93083edd29a65e73bb2e8eff9d353e92845c9b (patch)
tree596e34a8f006c18bf9984e87303dac546a048e5c /randr/rrmode.c
parent3bffb281260476d2f74f0bf451d85d2f7cacd6c4 (diff)
Add support for user-defined modelines in RandR.
The RandR protocol spec has several requests in support of user-defined modes, but the implementation was stubbed out inside the X server. Fill out the DIX portion and start on the xf86 DDX portion. It might be necessary to add more code to the DDX to insert the user-defined modes into the output mode list. (cherry picked from commit 63cc2a51ef87130c632a874672a8c9167f14314e) Conflicts: randr/randrstr.h Updated code to work in master with recent security API changes.
Diffstat (limited to 'randr/rrmode.c')
-rw-r--r--randr/rrmode.c217
1 files changed, 186 insertions, 31 deletions
diff --git a/randr/rrmode.c b/randr/rrmode.c
index 261e1b75f..11175810c 100644
--- a/randr/rrmode.c
+++ b/randr/rrmode.c
@@ -48,25 +48,13 @@ RRModeEqual (xRRModeInfo *a, xRRModeInfo *b)
static int num_modes;
static RRModePtr *modes;
-RRModePtr
-RRModeGet (xRRModeInfo *modeInfo,
- const char *name)
+static RRModePtr
+RRModeCreate (xRRModeInfo *modeInfo,
+ const char *name,
+ ScreenPtr userScreen)
{
- int i;
- RRModePtr mode;
- RRModePtr *newModes;
-
- for (i = 0; i < num_modes; i++)
- {
- mode = modes[i];
- if (RRModeEqual (&mode->mode, modeInfo) &&
- !memcmp (name, mode->name, modeInfo->nameLength))
- {
- ++mode->refcnt;
- return mode;
- }
- }
-
+ RRModePtr mode, *newModes;
+
if (!RRInit ())
return NULL;
@@ -78,7 +66,7 @@ RRModeGet (xRRModeInfo *modeInfo,
mode->name = (char *) (mode + 1);
memcpy (mode->name, name, modeInfo->nameLength);
mode->name[modeInfo->nameLength] = '\0';
- mode->userDefined = FALSE;
+ mode->userScreen = userScreen;
if (num_modes)
newModes = xrealloc (modes, (num_modes + 1) * sizeof (RRModePtr));
@@ -104,11 +92,75 @@ RRModeGet (xRRModeInfo *modeInfo,
return mode;
}
+static RRModePtr
+RRModeFindByName (const char *name,
+ CARD16 nameLength)
+{
+ int i;
+ RRModePtr mode;
+
+ for (i = 0; i < num_modes; i++)
+ {
+ mode = modes[i];
+ if (mode->mode.nameLength == nameLength &&
+ !memcmp (name, mode->name, nameLength))
+ {
+ return mode;
+ }
+ }
+ return NULL;
+}
+
+RRModePtr
+RRModeGet (xRRModeInfo *modeInfo,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < num_modes; i++)
+ {
+ RRModePtr mode = modes[i];
+ if (RRModeEqual (&mode->mode, modeInfo) &&
+ !memcmp (name, mode->name, modeInfo->nameLength))
+ {
+ ++mode->refcnt;
+ return mode;
+ }
+ }
+
+ return RRModeCreate (modeInfo, name, NULL);
+}
+
+static RRModePtr
+RRModeCreateUser (ScreenPtr pScreen,
+ xRRModeInfo *modeInfo,
+ const char *name,
+ int *error)
+{
+ RRModePtr mode;
+
+ mode = RRModeFindByName (name, modeInfo->nameLength);
+ if (mode)
+ {
+ *error = BadName;
+ return NULL;
+ }
+
+ mode = RRModeCreate (modeInfo, name, pScreen);
+ if (!mode)
+ {
+ *error = BadAlloc;
+ return NULL;
+ }
+ *error = Success;
+ return mode;
+}
+
RRModePtr *
RRModesForScreen (ScreenPtr pScreen, int *num_ret)
{
rrScrPriv(pScreen);
- int o, c;
+ int o, c, m;
RRModePtr *screen_modes;
int num_screen_modes = 0;
@@ -122,9 +174,11 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret)
RROutputPtr output = pScrPriv->outputs[o];
int m, n;
- for (m = 0; m < output->numModes; m++)
+ for (m = 0; m < output->numModes + output->numUserModes; m++)
{
- RRModePtr mode = output->modes[m];
+ RRModePtr mode = (m < output->numModes ?
+ output->modes[m] :
+ output->userModes[m-output->numModes]);
for (n = 0; n < num_screen_modes; n++)
if (screen_modes[n] == mode)
break;
@@ -150,6 +204,23 @@ RRModesForScreen (ScreenPtr pScreen, int *num_ret)
if (n == num_screen_modes)
screen_modes[num_screen_modes++] = mode;
}
+ /*
+ * Add all user modes for this screen
+ */
+ for (m = 0; m < num_modes; m++)
+ {
+ RRModePtr mode = modes[m];
+ int n;
+
+ if (mode->userScreen != pScreen)
+ continue;
+ for (n = 0; n < num_screen_modes; n++)
+ if (screen_modes[n] == mode)
+ break;
+ if (n == num_screen_modes)
+ screen_modes[num_screen_modes++] = mode;
+ }
+
*num_ret = num_screen_modes;
return screen_modes;
}
@@ -205,38 +276,122 @@ int
ProcRRCreateMode (ClientPtr client)
{
REQUEST(xRRCreateModeReq);
+ xRRCreateModeReply rep;
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ rrScrPrivPtr pScrPriv;
+ xRRModeInfo *modeInfo;
+ long units_after;
+ char *name;
+ int error, rc;
+ RRModePtr mode;
+
+ REQUEST_AT_LEAST_SIZE (xRRCreateModeReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ pScreen = pWin->drawable.pScreen;
+ pScrPriv = rrGetScrPriv(pScreen);
- REQUEST_SIZE_MATCH(xRRCreateModeReq);
- (void) stuff;
- return BadImplementation;
+ modeInfo = &stuff->modeInfo;
+ name = (char *) (stuff + 1);
+ units_after = (stuff->length - (sizeof (xRRCreateModeReq) >> 2));
+
+ /* check to make sure requested name fits within the data provided */
+ if ((int) (modeInfo->nameLength + 3) >> 2 > units_after)
+ return BadLength;
+
+ mode = RRModeCreateUser (pScreen, modeInfo, name, &error);
+ if (!mode)
+ return error;
+
+ rep.type = X_Reply;
+ rep.pad0 = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.mode = mode->mode.id;
+ if (client->swapped)
+ {
+ int n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.mode, n);
+ }
+ WriteToClient(client, sizeof(xRRCreateModeReply), (char *)&rep);
+
+ return client->noClientException;
}
int
ProcRRDestroyMode (ClientPtr client)
{
REQUEST(xRRDestroyModeReq);
+ RRModePtr mode;
REQUEST_SIZE_MATCH(xRRDestroyModeReq);
- (void) stuff;
- return BadImplementation;
+ mode = LookupIDByType (stuff->mode, RRModeType);
+ if (!mode)
+ {
+ client->errorValue = stuff->mode;
+ return RRErrorBase + BadRRMode;
+ }
+ if (!mode->userScreen)
+ return BadMatch;
+ if (mode->refcnt > 1)
+ return BadAccess;
+ FreeResource (stuff->mode, 0);
+ return Success;
}
int
ProcRRAddOutputMode (ClientPtr client)
{
REQUEST(xRRAddOutputModeReq);
+ RRModePtr mode;
+ RROutputPtr output;
REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
- (void) stuff;
- return BadImplementation;
+ output = LookupOutput(client, stuff->output, DixReadAccess);
+
+ if (!output)
+ {
+ client->errorValue = stuff->output;
+ return RRErrorBase + BadRROutput;
+ }
+
+ mode = LookupIDByType (stuff->mode, RRModeType);
+ if (!mode)
+ {
+ client->errorValue = stuff->mode;
+ return RRErrorBase + BadRRMode;
+ }
+
+ return RROutputAddUserMode (output, mode);
}
int
ProcRRDeleteOutputMode (ClientPtr client)
{
REQUEST(xRRDeleteOutputModeReq);
+ RRModePtr mode;
+ RROutputPtr output;
REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
- (void) stuff;
- return BadImplementation;
+ output = LookupOutput(client, stuff->output, DixReadAccess);
+
+ if (!output)
+ {
+ client->errorValue = stuff->output;
+ return RRErrorBase + BadRROutput;
+ }
+
+ mode = LookupIDByType (stuff->mode, RRModeType);
+ if (!mode)
+ {
+ client->errorValue = stuff->mode;
+ return RRErrorBase + BadRRMode;
+ }
+
+ return RROutputDeleteUserMode (output, mode);
}