mirror of
https://github.com/encounter/SDL.git
synced 2025-05-22 07:11:23 +00:00
x11: Hook up display hotplug notifications.
Obviously this needs XRandR support. Fixes #4977.
This commit is contained in:
parent
6b4bd5a759
commit
a236bf4f25
@ -785,6 +785,12 @@ X11_DispatchEvent(_THIS, XEvent *xevent)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
||||||
|
if (videodata->xrandr_event_base && (xevent->type == (videodata->xrandr_event_base + RRNotify))) {
|
||||||
|
X11_HandleXRandREvent(_this, xevent);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Send a SDL_SYSWMEVENT if the application wants them */
|
/* Send a SDL_SYSWMEVENT if the application wants them */
|
||||||
if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
|
if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
|
||||||
SDL_SysWMmsg wmmsg;
|
SDL_SysWMmsg wmmsg;
|
||||||
|
@ -313,66 +313,11 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
X11_InitModes_XRandR(_THIS)
|
X11_AddXRandRDisplay(_THIS, Display *dpy, int screen, RROutput outputid, XRRScreenResources *res)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
|
||||||
Display *dpy = data->display;
|
|
||||||
const int screencount = ScreenCount(dpy);
|
|
||||||
const int default_screen = DefaultScreen(dpy);
|
|
||||||
RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
|
|
||||||
Atom EDID = X11_XInternAtom(dpy, "EDID", False);
|
Atom EDID = X11_XInternAtom(dpy, "EDID", False);
|
||||||
XRRScreenResources *res = NULL;
|
|
||||||
Uint32 pixelformat;
|
|
||||||
XVisualInfo vinfo;
|
|
||||||
XPixmapFormatValues *pixmapformats;
|
|
||||||
int looking_for_primary;
|
|
||||||
int scanline_pad;
|
|
||||||
int output;
|
|
||||||
int screen, i, n;
|
|
||||||
|
|
||||||
for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
|
|
||||||
for (screen = 0; screen < screencount; screen++) {
|
|
||||||
|
|
||||||
/* we want the primary output first, and then skipped later. */
|
|
||||||
if (looking_for_primary && (screen != default_screen)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_visualinfo(dpy, screen, &vinfo) < 0) {
|
|
||||||
continue; /* uh, skip this screen? */
|
|
||||||
}
|
|
||||||
|
|
||||||
pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
|
||||||
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
|
||||||
continue; /* Palettized video modes are no longer supported */
|
|
||||||
}
|
|
||||||
|
|
||||||
scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
|
||||||
pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
|
||||||
if (pixmapformats) {
|
|
||||||
for (i = 0; i < n; ++i) {
|
|
||||||
if (pixmapformats[i].depth == vinfo.depth) {
|
|
||||||
scanline_pad = pixmapformats[i].scanline_pad;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
X11_XFree(pixmapformats);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
|
|
||||||
if (!res || res->noutput == 0) {
|
|
||||||
if (res) {
|
|
||||||
X11_XRRFreeScreenResources(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
|
||||||
if (!res) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (output = 0; output < res->noutput; output++) {
|
|
||||||
XRROutputInfo *output_info;
|
XRROutputInfo *output_info;
|
||||||
int display_x, display_y;
|
int display_x, display_y;
|
||||||
unsigned long display_mm_width, display_mm_height;
|
unsigned long display_mm_width, display_mm_height;
|
||||||
@ -384,18 +329,38 @@ X11_InitModes_XRandR(_THIS)
|
|||||||
RRMode modeID;
|
RRMode modeID;
|
||||||
RRCrtc output_crtc;
|
RRCrtc output_crtc;
|
||||||
XRRCrtcInfo *crtc;
|
XRRCrtcInfo *crtc;
|
||||||
|
XVisualInfo vinfo;
|
||||||
|
Uint32 pixelformat;
|
||||||
|
XPixmapFormatValues *pixmapformats;
|
||||||
|
int scanline_pad;
|
||||||
int xft_dpi = 0;
|
int xft_dpi = 0;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
/* The primary output _should_ always be sorted first, but just in case... */
|
if (get_visualinfo(dpy, screen, &vinfo) < 0) {
|
||||||
if ((looking_for_primary && (res->outputs[output] != primary)) ||
|
return 0; /* uh, skip this screen? */
|
||||||
(!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output_info = X11_XRRGetOutputInfo(dpy, res, res->outputs[output]);
|
pixelformat = X11_GetPixelFormatFromVisualInfo(dpy, &vinfo);
|
||||||
|
if (SDL_ISPIXELFORMAT_INDEXED(pixelformat)) {
|
||||||
|
return 0; /* Palettized video modes are no longer supported, ignore this one. */
|
||||||
|
}
|
||||||
|
|
||||||
|
scanline_pad = SDL_BYTESPERPIXEL(pixelformat) * 8;
|
||||||
|
pixmapformats = X11_XListPixmapFormats(dpy, &n);
|
||||||
|
if (pixmapformats) {
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
if (pixmapformats[i].depth == vinfo.depth) {
|
||||||
|
scanline_pad = pixmapformats[i].scanline_pad;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
X11_XFree(pixmapformats);
|
||||||
|
}
|
||||||
|
|
||||||
|
output_info = X11_XRRGetOutputInfo(dpy, res, outputid);
|
||||||
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
if (!output_info || !output_info->crtc || output_info->connection == RR_Disconnected) {
|
||||||
X11_XRRFreeOutputInfo(output_info);
|
X11_XRRFreeOutputInfo(output_info);
|
||||||
continue;
|
return 0; /* ignore this one. */
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
|
SDL_strlcpy(display_name, output_info->name, sizeof(display_name));
|
||||||
@ -406,7 +371,7 @@ X11_InitModes_XRandR(_THIS)
|
|||||||
|
|
||||||
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
|
crtc = X11_XRRGetCrtcInfo(dpy, res, output_crtc);
|
||||||
if (!crtc) {
|
if (!crtc) {
|
||||||
continue;
|
return 0; /* oh well, ignore it. */
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_zero(mode);
|
SDL_zero(mode);
|
||||||
@ -430,6 +395,7 @@ X11_InitModes_XRandR(_THIS)
|
|||||||
SDL_free(displaydata);
|
SDL_free(displaydata);
|
||||||
return SDL_OutOfMemory();
|
return SDL_OutOfMemory();
|
||||||
}
|
}
|
||||||
|
|
||||||
modedata->xrandr_mode = modeID;
|
modedata->xrandr_mode = modeID;
|
||||||
mode.driverdata = modedata;
|
mode.driverdata = modedata;
|
||||||
|
|
||||||
@ -440,21 +406,21 @@ X11_InitModes_XRandR(_THIS)
|
|||||||
displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f;
|
displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f;
|
||||||
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
|
displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f);
|
||||||
|
|
||||||
/* if xft dpi is available we will use this over xrandr */
|
/* if xft dpi is available we will use this over xrandr (!!! FIXME: ...yeah?) */
|
||||||
xft_dpi = GetXftDPI(dpy);
|
xft_dpi = GetXftDPI(dpy);
|
||||||
if(xft_dpi > 0) {
|
if (xft_dpi > 0) {
|
||||||
displaydata->hdpi = (float)xft_dpi;
|
displaydata->hdpi = (float) xft_dpi;
|
||||||
displaydata->vdpi = (float)xft_dpi;
|
displaydata->vdpi = (float) xft_dpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
displaydata->scanline_pad = scanline_pad;
|
displaydata->scanline_pad = scanline_pad;
|
||||||
displaydata->x = display_x;
|
displaydata->x = display_x;
|
||||||
displaydata->y = display_y;
|
displaydata->y = display_y;
|
||||||
displaydata->use_xrandr = SDL_TRUE;
|
displaydata->use_xrandr = SDL_TRUE;
|
||||||
displaydata->xrandr_output = res->outputs[output];
|
displaydata->xrandr_output = outputid;
|
||||||
|
|
||||||
SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
|
SetXRandRModeInfo(dpy, res, output_crtc, modeID, &mode);
|
||||||
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), res->outputs[output], display_mm_width, display_mm_height);
|
SetXRandRDisplayName(dpy, EDID, display_name, sizeof (display_name), outputid, display_mm_width, display_mm_height);
|
||||||
|
|
||||||
SDL_zero(display);
|
SDL_zero(display);
|
||||||
if (*display_name) {
|
if (*display_name) {
|
||||||
@ -463,10 +429,131 @@ X11_InitModes_XRandR(_THIS)
|
|||||||
display.desktop_mode = mode;
|
display.desktop_mode = mode;
|
||||||
display.current_mode = mode;
|
display.current_mode = mode;
|
||||||
display.driverdata = displaydata;
|
display.driverdata = displaydata;
|
||||||
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
return SDL_AddVideoDisplay(&display, SDL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
X11_HandleXRandROutputChange(_THIS, const XRROutputChangeNotifyEvent *ev)
|
||||||
|
{
|
||||||
|
const int num_displays = SDL_GetNumVideoDisplays();
|
||||||
|
SDL_VideoDisplay *display = NULL;
|
||||||
|
int displayidx = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
printf("XRROutputChangeNotifyEvent! [output=%u, crtc=%u, mode=%u, rotation=%u, connection=%u]", (unsigned int) ev->output, (unsigned int) ev->crtc, (unsigned int) ev->mode, (unsigned int) ev->rotation, (unsigned int) ev->connection);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (i = 0; i < num_displays; i++) {
|
||||||
|
SDL_VideoDisplay *thisdisplay = SDL_GetDisplay(i);
|
||||||
|
const SDL_DisplayData *displaydata = (const SDL_DisplayData *) thisdisplay->driverdata;
|
||||||
|
if (displaydata->xrandr_output == ev->output) {
|
||||||
|
display = thisdisplay;
|
||||||
|
displayidx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_assert((displayidx == -1) == (display == NULL));
|
||||||
|
|
||||||
|
if (ev->connection == RR_Disconnected) { /* output is going away */
|
||||||
|
if (display != NULL) {
|
||||||
|
SDL_DelVideoDisplay(displayidx);
|
||||||
|
}
|
||||||
|
} else if (ev->connection == RR_Connected) { /* output is coming online */
|
||||||
|
if (display != NULL) {
|
||||||
|
/* !!! FIXME: update rotation or current mode of existing display? */
|
||||||
|
} else {
|
||||||
|
Display *dpy = ev->display;
|
||||||
|
const int screen = DefaultScreen(dpy);
|
||||||
|
XVisualInfo vinfo;
|
||||||
|
if (get_visualinfo(dpy, screen, &vinfo) == 0) {
|
||||||
|
XRRScreenResources *res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
|
||||||
|
if (!res || res->noutput == 0) {
|
||||||
|
if (res) {
|
||||||
|
X11_XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
X11_AddXRandRDisplay(_this, dpy, screen, ev->output, res);
|
||||||
|
X11_XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
X11_HandleXRandREvent(_THIS, const XEvent *xevent)
|
||||||
|
{
|
||||||
|
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
||||||
|
SDL_assert(xevent->type == (videodata->xrandr_event_base + RRNotify));
|
||||||
|
|
||||||
|
switch (((const XRRNotifyEvent *) xevent)->subtype) {
|
||||||
|
case RRNotify_OutputChange:
|
||||||
|
X11_HandleXRandROutputChange(_this, (const XRROutputChangeNotifyEvent *) xevent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
X11_InitModes_XRandR(_THIS)
|
||||||
|
{
|
||||||
|
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
|
||||||
|
Display *dpy = data->display;
|
||||||
|
const int screencount = ScreenCount(dpy);
|
||||||
|
const int default_screen = DefaultScreen(dpy);
|
||||||
|
RROutput primary = X11_XRRGetOutputPrimary(dpy, RootWindow(dpy, default_screen));
|
||||||
|
XRRScreenResources *res = NULL;
|
||||||
|
int xrandr_error_base = 0;
|
||||||
|
int looking_for_primary;
|
||||||
|
int output;
|
||||||
|
int screen;
|
||||||
|
|
||||||
|
if (!X11_XRRQueryExtension(dpy, &data->xrandr_event_base, &xrandr_error_base)) {
|
||||||
|
return SDL_SetError("XRRQueryExtension failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (looking_for_primary = 1; looking_for_primary >= 0; looking_for_primary--) {
|
||||||
|
for (screen = 0; screen < screencount; screen++) {
|
||||||
|
|
||||||
|
/* we want the primary output first, and then skipped later. */
|
||||||
|
if (looking_for_primary && (screen != default_screen)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = X11_XRRGetScreenResourcesCurrent(dpy, RootWindow(dpy, screen));
|
||||||
|
if (!res || res->noutput == 0) {
|
||||||
|
if (res) {
|
||||||
|
X11_XRRFreeScreenResources(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = X11_XRRGetScreenResources(dpy, RootWindow(dpy, screen));
|
||||||
|
if (!res) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (output = 0; output < res->noutput; output++) {
|
||||||
|
/* The primary output _should_ always be sorted first, but just in case... */
|
||||||
|
if ((looking_for_primary && (res->outputs[output] != primary)) ||
|
||||||
|
(!looking_for_primary && (screen == default_screen) && (res->outputs[output] == primary))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (X11_AddXRandRDisplay(_this, dpy, screen, res->outputs[output], res) == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
X11_XRRFreeScreenResources(res);
|
X11_XRRFreeScreenResources(res);
|
||||||
|
|
||||||
|
/* This will generate events for displays that come and go at runtime. */
|
||||||
|
X11_XRRSelectInput(dpy, RootWindow(dpy, screen), RROutputChangeNotifyMask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +651,7 @@ static int X11_InitModes_StdXlib(_THIS)
|
|||||||
display.desktop_mode = mode;
|
display.desktop_mode = mode;
|
||||||
display.current_mode = mode;
|
display.current_mode = mode;
|
||||||
display.driverdata = displaydata;
|
display.driverdata = displaydata;
|
||||||
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
SDL_AddVideoDisplay(&display, SDL_TRUE);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,10 @@ extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect
|
|||||||
extern int X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
|
extern int X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
|
||||||
extern int X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
|
extern int X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
|
||||||
|
|
||||||
|
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
||||||
|
extern void X11_HandleXRandREvent(_THIS, const XEvent *xevent);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SDL_x11modes_h_ */
|
#endif /* SDL_x11modes_h_ */
|
||||||
|
|
||||||
/* vi: set ts=4 sw=4 expandtab: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
@ -276,6 +276,7 @@ SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c
|
|||||||
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
#if SDL_VIDEO_DRIVER_X11_XRANDR
|
||||||
SDL_X11_MODULE(XRANDR)
|
SDL_X11_MODULE(XRANDR)
|
||||||
SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return)
|
SDL_X11_SYM(Status,XRRQueryVersion,(Display *dpy,int *major_versionp,int *minor_versionp),(dpy,major_versionp,minor_versionp),return)
|
||||||
|
SDL_X11_SYM(Bool,XRRQueryExtension,(Display *dpy,int *event_base_return,int *error_base_return),(dpy,event_base_return,error_base_return),return);
|
||||||
SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return)
|
SDL_X11_SYM(XRRScreenConfiguration *,XRRGetScreenInfo,(Display *dpy,Drawable draw),(dpy,draw),return)
|
||||||
SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return)
|
SDL_X11_SYM(SizeID,XRRConfigCurrentConfiguration,(XRRScreenConfiguration *config,Rotation *rotation),(config,rotation),return)
|
||||||
SDL_X11_SYM(short,XRRConfigCurrentRate,(XRRScreenConfiguration *config),(config),return)
|
SDL_X11_SYM(short,XRRConfigCurrentRate,(XRRScreenConfiguration *config),(config),return)
|
||||||
@ -297,6 +298,7 @@ SDL_X11_SYM(Atom*,XRRListOutputProperties,(Display *dpy, RROutput output, int *n
|
|||||||
SDL_X11_SYM(XRRPropertyInfo*,XRRQueryOutputProperty,(Display *dpy,RROutput output, Atom property),(dpy,output,property),return)
|
SDL_X11_SYM(XRRPropertyInfo*,XRRQueryOutputProperty,(Display *dpy,RROutput output, Atom property),(dpy,output,property),return)
|
||||||
SDL_X11_SYM(int,XRRGetOutputProperty,(Display *dpy,RROutput output, Atom property, long offset, long length, Bool _delete, Bool pending, Atom req_type, Atom *actual_type, int *actual_format, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop),(dpy,output,property,offset,length, _delete, pending, req_type, actual_type, actual_format, nitems, bytes_after, prop),return)
|
SDL_X11_SYM(int,XRRGetOutputProperty,(Display *dpy,RROutput output, Atom property, long offset, long length, Bool _delete, Bool pending, Atom req_type, Atom *actual_type, int *actual_format, unsigned long *nitems, unsigned long *bytes_after, unsigned char **prop),(dpy,output,property,offset,length, _delete, pending, req_type, actual_type, actual_format, nitems, bytes_after, prop),return)
|
||||||
SDL_X11_SYM(RROutput,XRRGetOutputPrimary,(Display *dpy,Window window),(dpy,window),return)
|
SDL_X11_SYM(RROutput,XRRGetOutputPrimary,(Display *dpy,Window window),(dpy,window),return)
|
||||||
|
SDL_X11_SYM(void,XRRSelectInput,(Display *dpy, Window window, int mask),(dpy,window,mask),)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MIT-SCREEN-SAVER support */
|
/* MIT-SCREEN-SAVER support */
|
||||||
|
@ -134,6 +134,8 @@ typedef struct SDL_VideoData
|
|||||||
SDL_Point global_mouse_position;
|
SDL_Point global_mouse_position;
|
||||||
Uint32 global_mouse_buttons;
|
Uint32 global_mouse_buttons;
|
||||||
|
|
||||||
|
int xrandr_event_base;
|
||||||
|
|
||||||
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
|
||||||
XkbDescPtr xkb;
|
XkbDescPtr xkb;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user