We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5289

Summary: X11: CreateWindowFrom doesn't register for window events and thus doesn't show anything
Product: SDL Reporter: michaeljosephmaltese
Component: videoAssignee: Sam Lantinga <slouken>
Status: NEW --- QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: michaeljosephmaltese, sezeroz
Version: HG 2.1   
Hardware: All   
OS: Linux   

Description michaeljosephmaltese 2020-09-15 19:41:41 UTC
When using CreateWindowFrom with an X11 Window/XID, SDL displays anything. This is because it never registers for  events on the window, which are needed to know when the window is shown and what size it is.

An additional complication is that the events SDL is interested in includes ButtonPressMask - requesting this event can throw an error if another client (e.g., the source of the foreign window) has already registered for that event.

So, SDL's X11 backend needs to register for the same events in CreateWindowFrom as it does in CreateWindow, except sometimes it needs to not register for ButtonPress.

Something like this might work (doesn't do the other logic CreateWindow does around events, in the interest of sketching out something that works):

```
static SDL_bool xselectinputerror;

int xselectinputerrorhandler(Display *d, XErrorEvent *e) {
        xselectinputerror = SDL_TRUE;
        return 0;
}

int
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
    SDL_VideoData *driverdata = (SDL_VideoData *) _this->driverdata;
    Display *display = driverdata->display;
    Window w = (Window) data;
    long event_mask;
    int (*old_handler)(Display*, XErrorEvent*);

    window->title = X11_GetWindowTitle(_this, w);

    if (SetupWindowData(_this, window, w, SDL_FALSE) < 0) {
        return -1;
    }

    X11_XSync(display, False);
    old_handler = X11_XSetErrorHandler(xselectinputerrorhandler);
    event_mask =
                 (FocusChangeMask | EnterWindowMask | LeaveWindowMask |
                 ExposureMask |  ButtonPressMask | ButtonReleaseMask |
                 PointerMotionMask | KeyPressMask | KeyReleaseMask |
                 PropertyChangeMask | StructureNotifyMask |
                 KeymapStateMask);
    xselectinputerror = SDL_FALSE;
    X11_XSelectInput(display, w, event_mask);
    X11_XSync(display, False);
    if (xselectinputerror) {
        event_mask &= ~ButtonPressMask;
        xselectinputerror = SDL_FALSE;
        X11_XSelectInput(display, w, event_mask);
        X11_XSync(display, False);
        if (xselectinputerror) {
                SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us register for window events.");
                return -1;
        }
        SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "The X server refused to let us register for button press events. You might experience input bugs.");
    }

    X11_XSetErrorHandler(old_handler);

    return 0;
}
```