示例#1
0
// this should be called from XRobotPeer constructor
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls, jint numberOfButtons, jintArray buttonDownMasks)
{
    int32_t xtestAvailable;
    jint *tmp;
    int i;

    DTRACE_PRINTLN("RobotPeer: setup()");

    num_buttons = numberOfButtons;
    tmp = (*env)->GetIntArrayElements(env, buttonDownMasks, JNI_FALSE);
    masks = (jint *)malloc(sizeof(jint) * num_buttons);
    if (masks == (jint *) NULL) {
        JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL);
        (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);
        return;
    }
    for (i = 0; i < num_buttons; i++) {
        masks[i] = tmp[i];
    }
    (*env)->ReleaseIntArrayElements(env, buttonDownMasks, tmp, 0);

    AWT_LOCK();
    xtestAvailable = isXTestAvailable();
    DTRACE_PRINTLN1("RobotPeer: XTest available = %d", xtestAvailable);
    if (!xtestAvailable) {
        JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
    }

    AWT_UNLOCK();
}
示例#2
0
static HDC Win32OSSD_GetDC(JNIEnv *env, Win32SDOps *wsdo,
                           jint type, jint *patrop,
                           jobject clip, jobject comp, jint color)
{
    // REMIND: Should lock around all accesses to "last<mumble>"
    DTRACE_PRINTLN1("Win32OSSD.GetDC, color = 0x%x", color);

    if (wsdo->invalid) {
	SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
	return (HDC) NULL;
    }

    HDC hdc = wsdo->lpSurface->GetDC();
    if (hdc == NULL) {
	// Note: DDrawSurface::GetDC() releases its surfaceLock
	// when it returns an error here, so do not call ReleaseDC()
	// to force the release of surfaceLock
	SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
	return (HDC) NULL;
    }

    // Initialize the DC
    Win32OSSD_InitDC(env, wsdo, hdc, type, patrop, clip, comp, color);
    return hdc;
}
示例#3
0
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env,
                           jclass cls,
                           jint wheelAmt) {
/* Mouse wheel is implemented as a button press of button 4 and 5, so it */
/* probably could have been hacked into robot_mouseButtonEvent, but it's */
/* cleaner to give it its own command type, in case the implementation   */
/* needs to be changed later.  -bchristi, 6/20/01                        */

    int32_t repeat = abs(wheelAmt);
    int32_t button = wheelAmt < 0 ? 4 : 5;  /* wheel up:   button 4 */
                                                 /* wheel down: button 5 */
    int32_t loopIdx;

    AWT_LOCK();

    DTRACE_PRINTLN1("RobotPeer: mouseWheelImpl(%i)", wheelAmt);

    for (loopIdx = 0; loopIdx < repeat; loopIdx++) { /* do nothing for   */
                                                     /* wheelAmt == 0    */
        XTestFakeButtonEvent(awt_display, button, True, CurrentTime);
        XTestFakeButtonEvent(awt_display, button, False, CurrentTime);
    }
    XSync(awt_display, False);

    AWT_UNLOCK();
}
示例#4
0
static int
awt_mgrsel_unmanaged(XDestroyWindowEvent *ev)
{
    Display *dpy = awt_display;
    struct AwtMgrsel *mgrsel;
    Window exowner;
    int scr;

    exowner = ev->window;	/* selection owner that's gone */

    /* is this a selection we are intrested in? */
    for (mgrsel = mgrsel_list; mgrsel != NULL; mgrsel = mgrsel->next) {
	for (scr = 0; scr < ScreenCount(dpy); ++scr) {
	    if (exowner == mgrsel->per_scr_owners[scr]) {
		/* can one window own selections for more than one screen? */
		goto out;	/* XXX??? */
	    }
	}
    }
  out:
    if (mgrsel == NULL) {
	DTRACE_PRINTLN1("MG: DestroyNotify for 0x%08lx ignored", exowner);
	return (0);
    }

    DTRACE_PRINTLN3("MG: DestroyNotify for 0x%08lx, owner of %s at screen %d",
		    exowner, mgrsel->selname, scr);

    /* notify the listener (pass exowner as data???) */
    if (mgrsel->callback_owner != NULL) {
	(*mgrsel->callback_owner)(scr, None, NULL, mgrsel->cookie);
    }

    return (1);
}
示例#5
0
void AwtDesktopProperties::SetFontProperty(LPCTSTR propName, const LOGFONT & font) {
    jstring fontName;
    jint pointSize;
    jint style;

    fontName = JNU_NewStringPlatform(GetEnv(), font.lfFaceName);

#if 0
    HDC		hdc;
    int		pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
    // convert font size specified in pixels to font size in points
    hdc = GetDC(NULL);
    pointSize = (-font.lfHeight)*72/pixelsPerInch;
    ReleaseDC(NULL, hdc);
#endif    
    // Java uses point sizes, but assumes 1 pixel = 1 point
    pointSize = -font.lfHeight;

    // convert Windows font style to Java style
    style = java_awt_Font_PLAIN;
    DTRACE_PRINTLN1("weight=%d", font.lfWeight);
    if ( font.lfWeight >= FW_BOLD ) {
	style =  java_awt_Font_BOLD;
    }
    if ( font.lfItalic ) {
	style |= java_awt_Font_ITALIC;
    }

    jstring key = JNU_NewStringPlatform(GetEnv(), propName);
    GetEnv()->CallVoidMethod(self, AwtDesktopProperties::setFontPropertyID,
			     key, fontName, style, pointSize);

    GetEnv()->DeleteLocalRef(fontName);
    GetEnv()->DeleteLocalRef(key);
}
示例#6
0
JNIEXPORT void JNICALL
Java_sun_awt_X11_XToolkit_initIDs
  (JNIEnv *env, jclass clazz)
{
    /* printf("Java_sun_awt_X11_XToolkit_initIDs\n");     */
    jfieldID fid = (*env)->GetStaticFieldID(env, clazz, "numLockMask", "I"); 
    awt_NumLockMask = (*env)->GetStaticIntField(env, clazz, fid); 
    DTRACE_PRINTLN1("awt_NumLockMask = %u", awt_NumLockMask); 
}
示例#7
0
JNIEXPORT void JNICALL
Java_sun_awt_X11_XToolkit_initIDs
  (JNIEnv *env, jclass clazz)
{
    jfieldID fid = (*env)->GetStaticFieldID(env, clazz, "numLockMask", "I"); 
    awt_NumLockMask = (*env)->GetStaticIntField(env, clazz, fid); 
    DTRACE_PRINTLN1("awt_NumLockMask = %u", awt_NumLockMask); 
    fid = (*env)->GetStaticFieldID(env, clazz, "modLockIsShiftLock", "I"); 
    awt_ModLockIsShiftLock = (*env)->GetStaticIntField(env, clazz, fid) != 0 ? True : False; 
}
示例#8
0
/*
  * Function joining the code of mousePressImpl and mouseReleaseImpl
  */
void mouseAction(JNIEnv *env,
                 jclass cls,
                 jint buttonMask,
                 Bool isMousePress)
{
    AWT_LOCK();

    DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask);
    DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress);

    if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ||
        buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK )
    {
        XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime);
    }
    if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ||
         buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) &&
        (num_buttons >= 2)) {
        XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime);
    }
    if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ||
         buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) &&
        (num_buttons >= 3)) {
        XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime);
    }

    if (num_buttons > 3){
        int32_t i;
        int32_t button = 0;
        for (i = 3; i<num_buttons; i++){
            if ((buttonMask & masks[i])) {
                // arrays starts from zero index => +1
                // users wants to affect 4 or 5 button but they are assigned
                // to the wheel so => we have to shift it to the right by 2.
                button = i + 3;
                XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime);
            }
        }
    }

    XSync(awt_display, False);
    AWT_UNLOCK();
}
/*
 * Class:     sun_awt_windows_WScrollPanePeer
 * Method:    _getVScrollbarWidth
 * Signature: ()I
 */
JNIEXPORT jint JNICALL
Java_sun_awt_windows_WScrollPanePeer__1getVScrollbarWidth(JNIEnv *env,
                                                          jobject self)
{
    TRY;

    DTRACE_PRINTLN1("%x: WScrollPanePeer._getVScrollbarHeight()", self);
    return ::GetSystemMetrics(SM_CXVSCROLL);

    CATCH_BAD_ALLOC_RET(0);
}
示例#10
0
/*
 * Given the JDK/JRE install directory form the name of the robot child process
 * e.g. Directory /foo/kestrel/jre -> Executable /foo/kestrel/jre/bin/awt_robot
 */
JNIEXPORT void JNICALL Java_sun_awt_motif_MRobotPeer_buildChildProcessName(
    JNIEnv *env, jclass cls, jstring installDir) {
    char * cdir;	

    cdir = (char *) JNU_GetStringPlatformChars(env, installDir, NULL);
    if (cdir == NULL) {
	return;
    }
    sprintf(RobotChildExePath, "%s/%s", cdir, ROBOT_EXE);
    DTRACE_PRINTLN1("Robot child process name is : %s", RobotChildExePath);
    JNU_ReleaseStringPlatformChars(env, installDir, cdir);
}
示例#11
0
JNIEXPORT void JNICALL Java_sun_awt_motif_MRobotPeer_setup(JNIEnv * env, jclass cls) {
    RCmdSetup cmd;
    RResultSetup result;

    DTRACE_PRINTLN("MRobotPeer.setup()");
    cmd.code = RCMD_SETUP;
    robot_writeChildCommand((RCmdBase *)&cmd);
    DTRACE_PRINTLN("PARENT: Waiting for setup result ...");
    robot_getChildResult((char *)&result, sizeof result);
    DTRACE_PRINTLN1("PARENT: XTest available = %d", result.isXTestAvailable);

    if (!result.isXTestAvailable) {
	JNU_ThrowByName(env, "java/awt/AWTException", "java.awt.Robot requires your X server support the XTEST extension version 2.2");
    }
}
/*
 * Class:     sun_awt_windows_WScrollPanePeer
 * Method:    setInsets
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WScrollPanePeer_setInsets(JNIEnv *env, jobject self)
{
    TRY

    DTRACE_PRINTLN1("%x: WScrollPanePeer.setInsets()", self);

    PDATA pData;
    JNI_CHECK_PEER_RETURN(self);
    AwtScrollPane* pane = (AwtScrollPane *)pData;
    pane->SetInsets(env);
    pane->VerifyState();

    CATCH_BAD_ALLOC;
}
示例#13
0
JNIEXPORT void JNICALL 
Java_sun_awt_windows_Win32OffScreenSurfaceData_initSurface(JNIEnv *env, 
							   jobject sData, 
							   jint depth, 
							   jint width,
							   jint height,
							   jint screen,
							   jboolean isVolatile,
                                                           jint transparency)
{
    Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, sData);

    DTRACE_PRINTLN("Win32OSSD_initSurface");
    initOSSD_WSDO(env, wsdo, width, height, screen, transparency);
    if (!DDCreateSurface(wsdo, isVolatile /* d3d caps desired, if possible */)) {
	DTRACE_PRINTLN1("Win32OSD.initSurface: Can't create offsc surf tr=%d\n",
			transparency);
	SurfaceData_ThrowInvalidPipeException(env, 
					      "Can't create offscreen surf");
    } else {
	wsdo->surfacePuntData.lpSurfaceVram = wsdo->lpSurface;
	if (!D3DEnabled(wsdo)) {
	    // d3d enabled by default for each surface - disable if necessary
	    env->SetBooleanField(sData, localD3dEnabledID, JNI_FALSE);
	} else {
	    env->SetBooleanField(sData, d3dClippingEnabledID, 
	    			 (DDINSTANCE_USABLE(wsdo->ddInstance) && 
	    			  wsdo->ddInstance->canClipD3dLines));
	}
    }
    // 8 is somewhat arbitrary; we want the threshhold to represent a
    // significant portion of the surface area in order to avoid
    // punting for occasional, small reads
    wsdo->surfacePuntData.pixelsReadThreshold = width * height / 8;
    /**
     * Only enable our punt-to-sysmem-surface scheme for surfaces that are:
     *   - non-transparent (we really only intended this workaround for
     *     back buffers, which are usually opaque)
     *   - volatile (non-volatile images should not even get into the punt
     *     situation since they should not be a rendering destination, but
     *     we check this just to make sure)
     * And only do so if the user did not specify that punting be disabled
     */
    wsdo->surfacePuntData.disablePunts = (transparency != TR_OPAQUE) ||
                                         !isVolatile                 ||
					 ddVramForced;
}
示例#14
0
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_keyReleaseImpl (JNIEnv *env,
                           jclass cls,
                           jint keycode) {
    AWT_LOCK();

    DTRACE_PRINTLN1("RobotPeer: keyReleaseImpl(%i)", keycode);

    XTestFakeKeyEvent(awt_display,
                      XKeysymToKeycode(awt_display, awt_getX11KeySym(keycode)),
                      False,
                      CurrentTime);

    XSync(awt_display, False);

    AWT_UNLOCK();
}
示例#15
0
static jint Win32OSSD_Lock(JNIEnv *env,
			   SurfaceDataOps *ops,
			   SurfaceDataRasInfo *pRasInfo,
			   jint lockflags)
{
    Win32SDOps *wsdo = (Win32SDOps *) ops;
    DTRACE_PRINTLN1("W32OSSD::Win32OSSD_Lock, lockflags = 0x%x", lockflags);
    wsdo->surfaceLock->Enter();
    if (wsdo->invalid) {
	wsdo->surfaceLock->Leave();
	SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
	return SD_FAILURE;
    }

    if (wsdo->lockType != WIN32SD_LOCK_UNLOCKED) {
	wsdo->surfaceLock->Leave();
	JNU_ThrowInternalError(env, "Win32OSSD_Lock cannot nest locks");
	return SD_FAILURE;
    }

    if (lockflags & SD_LOCK_RD_WR) {
	if (pRasInfo->bounds.x1 < 0) pRasInfo->bounds.x1 = 0;
	if (pRasInfo->bounds.y1 < 0) pRasInfo->bounds.y1 = 0;
	if (pRasInfo->bounds.x2 > wsdo->w) pRasInfo->bounds.x2 = wsdo->w;
	if (pRasInfo->bounds.y2 > wsdo->h) pRasInfo->bounds.y2 = wsdo->h;
	if (DDUseDDraw(wsdo)) {
	    Win32OSSD_LockByDD(env, wsdo, lockflags, pRasInfo);
	}
	if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
	    wsdo->lockFlags = lockflags;
	    wsdo->surfaceLock->Leave();
	    return SD_FAILURE;
	}
    } else {
	// They didn't ask for a lock, so they don't get one
	wsdo->lockType = WIN32SD_LOCK_BY_NULL;
    }
    wsdo->lockFlags = lockflags;
    DTRACE_PRINTLN2("Win32OSSD_Lock: flags, type = 0x%x, %d\n", 
	wsdo->lockFlags, wsdo->lockType);
    return 0;
}
void AwtScrollPane::_SetInsets(void *param)
{
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);

    jobject self = (jobject)param;

    AwtScrollPane *s = NULL;

    PDATA pData;
    JNI_CHECK_PEER_GOTO(self, ret);
    s = (AwtScrollPane *)pData;
    if (::IsWindow(s->GetHWnd()))
    {
        DTRACE_PRINTLN1("%x: WScrollPanePeer.setInsets()", self);
        s->SetInsets(env);
        s->VerifyState();
    }
ret:
   env->DeleteGlobalRef(self);
}
/*
 * Class:     sun_awt_windows_WScrollPanePeer
 * Method:    getScrollChild
 * Signature: ()Ljava/awt/Component;
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_windows_WScrollPanePeer_getScrollChild(JNIEnv *env, jobject self)
{
    TRY;

    DTRACE_PRINTLN1("%x: WScrollPanePeer.getScrollChild()", self);

    PDATA pData;
    JNI_CHECK_PEER_RETURN_NULL(self);
    jobject target = env->GetObjectField(self, AwtObject::targetID);
    jint ncomponents = 
        (env)->GetIntField(target, AwtContainer::ncomponentsID);

    if (ncomponents == 0) {
        JNU_ThrowNullPointerException(env, "child is null");
        return NULL;
    }
    jobjectArray components = 
	(jobjectArray)(env)->GetObjectField(target, AwtContainer::componentID);
    return env->GetObjectArrayElement(components, 0);

    CATCH_BAD_ALLOC_RET(NULL);
}
示例#18
0
DX5Object::~DX5Object()
{
    DTRACE_PRINTLN1("~DX5Object: ddObject = 0x%x\n", ddObject);
    ddObject->Release();
    ddObject = NULL;
}
示例#19
0
BOOL InitThemes() {
    static HMODULE hModThemes = NULL;
    hModThemes = JDK_LoadSystemLibrary("UXTHEME.DLL");
    DTRACE_PRINTLN1("InitThemes hModThemes = %x\n", hModThemes);
    if(hModThemes) {
        DTRACE_PRINTLN("Loaded UxTheme.dll\n");
        OpenThemeData = (PFNOPENTHEMEDATA)GetProcAddress(hModThemes,
                                                        "OpenThemeData");
        DrawThemeBackground = (PFNDRAWTHEMEBACKGROUND)GetProcAddress(
                                        hModThemes, "DrawThemeBackground");
        CloseThemeData = (PFNCLOSETHEMEDATA)GetProcAddress(
                                                hModThemes, "CloseThemeData");
        DrawThemeText = (PFNDRAWTHEMETEXT)GetProcAddress(
                                        hModThemes, "DrawThemeText");
        GetThemeBackgroundContentRect = (PFNGETTHEMEBACKGROUNDCONTENTRECT)
                GetProcAddress(hModThemes, "GetThemeBackgroundContentRect");
        GetThemeMargins = (PFNGETTHEMEMARGINS)GetProcAddress(
                                        hModThemes, "GetThemeMargins");
        IsThemePartDefined = (PFNISTHEMEPARTDEFINED)GetProcAddress(
                                        hModThemes, "IsThemePartDefined");
        GetThemeBool = (PFNGETTHEMEBOOL)GetProcAddress(
                                        hModThemes, "GetThemeBool");
        GetThemeSysBool = (PFNGETTHEMESYSBOOL)GetProcAddress(hModThemes,
                                                        "GetThemeSysBool");
        GetThemeColor = (PFNGETTHEMECOLOR)GetProcAddress(hModThemes,
                                                        "GetThemeColor");
        GetThemeEnumValue = (PFNGETTHEMEENUMVALUE)GetProcAddress(hModThemes,
                                                "GetThemeEnumValue");
        GetThemeInt = (PFNGETTHEMEINT)GetProcAddress(hModThemes, "GetThemeInt");
        GetThemePosition = (PFNGETTHEMEPOSITION)GetProcAddress(hModThemes,
                                                        "GetThemePosition");
        GetThemePartSize = (PFNGETTHEMEPARTSIZE)GetProcAddress(hModThemes,
                                                         "GetThemePartSize");
        SetWindowTheme = (PFNSETWINDOWTHEME)GetProcAddress(hModThemes,
                                                        "SetWindowTheme");
        IsThemeBackgroundPartiallyTransparent =
            (PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)GetProcAddress(hModThemes,
                                       "IsThemeBackgroundPartiallyTransparent");
        //this function might not exist
        GetThemeTransitionDuration =
            (PFNGETTHEMETRANSITIONDURATION)GetProcAddress(hModThemes,
                                        "GetThemeTransitionDuration");

        if(OpenThemeData
           && DrawThemeBackground
           && CloseThemeData
           && DrawThemeText
           && GetThemeBackgroundContentRect
           && GetThemeMargins
           && IsThemePartDefined
           && GetThemeBool
           && GetThemeSysBool
           && GetThemeColor
           && GetThemeEnumValue
           && GetThemeInt
           && GetThemePartSize
           && GetThemePosition
           && SetWindowTheme
           && IsThemeBackgroundPartiallyTransparent
          ) {
              DTRACE_PRINTLN("Loaded function pointers.\n");
              // We need to make sure we can load the Theme. This may not be
              // the case on a WinXP machine with classic mode enabled.
              HTHEME hTheme = OpenThemeData(AwtToolkit::GetInstance().GetHWnd(), L"Button");
              if(hTheme) {
                  DTRACE_PRINTLN("Loaded Theme data.\n");
                  CloseThemeData(hTheme);
                  return TRUE;
              }
            } else {
               FreeLibrary(hModThemes);
               hModThemes = NULL;
            }
    }
    return FALSE;
}
示例#20
0
/*
 * A method for a subsytem to express its interest in a certain
 * manager selection.
 *
 * If owner changes, the callback_owner will be called with the screen
 * number and the new owning window when onwership is established, or
 * None if the owner is gone.
 *
 * Events in extra_mask are selected for on owning windows (exsiting
 * ones and on new owners when established) and callback_event will be
 * called with the screen number and an event.
 * 
 * The function returns an array of current owners.  The size of the
 * array is ScreenCount(awt_display).  The array is "owned" by this
 * module and should be considered by the caller as read-only.
 */
const Window *
awt_mgrsel_select(const char *selname, long extra_mask,
		  void *cookie,
		  void (*callback_event)(int, XEvent *, void *),
		  void (*callback_owner)(int, Window, long *, void *))
{
    Display *dpy = awt_display;
    struct AwtMgrsel *mgrsel;
    Atom *per_scr_atoms;
    Window *per_scr_owners;
    char *namesbuf;
    char **names;
    int per_scr_sz;
    int nscreens = ScreenCount(dpy);
    int scr;
    Status status;

    DASSERT(selname != NULL);
    DTRACE_PRINTLN1("MG: select: %s", selname);

    /* buffer size for one per-screen atom name */
    per_scr_sz = strlen(selname) + /* "_S" */ 2 + /* %2d */ + 2 /* '\0' */+ 1;

    namesbuf = malloc(per_scr_sz * nscreens);  /* actual storage for names */
    names = malloc(sizeof(char *) * nscreens); /* pointers to names */
    per_scr_atoms = malloc(sizeof(Atom) * nscreens);
    per_scr_owners = malloc(sizeof(Window) * nscreens);
    mgrsel = malloc(sizeof(struct AwtMgrsel));

    if (namesbuf == NULL || names == NULL || per_scr_atoms == NULL
	|| per_scr_owners == NULL || mgrsel == NULL)
    {
	DTRACE_PRINTLN("MG: select: unable to allocate memory");
	if (namesbuf != NULL) free(per_scr_atoms);
	if (names != NULL) free(names);
	if (per_scr_atoms != NULL) free(per_scr_atoms);
	if (per_scr_owners != NULL) free(per_scr_owners);
	if (mgrsel != NULL) free(mgrsel);
	return (NULL);
    }


    for (scr = 0; scr < nscreens; ++scr) {
	size_t sz;

	names[scr] = &namesbuf[per_scr_sz * scr];
	sz = snprintf(names[scr], per_scr_sz, "%s_S%-d", selname, scr);
	DASSERT(sz < per_scr_sz);
    }

    status = XInternAtoms(dpy, names, nscreens, False, per_scr_atoms);

    free(names);
    free(namesbuf);

    if (status == 0) {
	DTRACE_PRINTLN("MG: select: XInternAtoms failed");
	free(per_scr_atoms);
	free(per_scr_owners);
	return (NULL);
    }

    mgrsel->selname = strdup(selname);
    mgrsel->per_scr_atoms = per_scr_atoms;
    mgrsel->per_scr_owners = per_scr_owners;
    mgrsel->extra_mask = extra_mask;
    mgrsel->cookie = cookie;
    mgrsel->callback_event = callback_event;
    mgrsel->callback_owner = callback_owner;

    for (scr = 0; scr < nscreens; ++scr) {
	Window owner;

	owner = awt_mgrsel_select_per_screen(per_scr_atoms[scr], extra_mask);
	mgrsel->per_scr_owners[scr] = owner;
#ifdef DEBUG
	if (owner == None) {
	    DTRACE_PRINTLN1("MG:   screen %d - None", scr);
	} else {
	    DTRACE_PRINTLN2("MG:   screen %d - 0x%08lx", scr, owner);
	}
#endif
    }

    mgrsel->next = mgrsel_list;
    mgrsel_list = mgrsel;

    return (per_scr_owners);
}