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 - X11: CreateWindowFrom doesn't register for window events and thus doesn't show anything
Summary: X11: CreateWindowFrom doesn't register for window events and thus doesn't sho...
Status: NEW
Alias: None
Product: SDL
Classification: Unclassified
Component: video (show other bugs)
Version: HG 2.1
Hardware: All Linux
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-09-15 19:41 UTC by michaeljosephmaltese
Modified: 2020-10-18 10:41 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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;
}
```