Skip to content
Snippets Groups Projects
Commit a10cf76b authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Start laying the groundwork for X11 fullscreen mode.

This is the last feature that SDL mode provides that X11 mode is
lacking.  I rarely use it myself, but it should be there.
parent 19684258
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Pipeline #4411 passed
......@@ -83,6 +83,14 @@ ifndef NO_X
CIOLIB-MT_CFLAGS += $(shell pkg-config xrender --cflags)
CIOLIB-MT_CFLAGS += -DWITH_XRENDER
endif
ifeq ($(shell pkg-config xinerama --exists && echo YES), YES)
CIOLIB-MT_CFLAGS += $(shell pkg-config xinerama --cflags)
CIOLIB-MT_CFLAGS += -DWITH_XINERAMA
endif
ifeq ($(shell pkg-config xrandr --exists && echo YES), YES)
CIOLIB-MT_CFLAGS += $(shell pkg-config xrandr --cflags)
CIOLIB-MT_CFLAGS += -DWITH_XRANDR
endif
endif
# Find SDL headers!
......
......@@ -215,8 +215,18 @@ int x_init(void)
{
dll_handle dl;
const char *libnames[]={"X11",NULL};
#ifdef WITH_XRENDER
dll_handle dl2;
const char *libnames2[]={"Xrender",NULL};
#endif
#ifdef WITH_XINERAMA
dll_handle dl3;
const char *libnames3[]={"Xinerama",NULL};
#endif
#ifdef WITH_XRANDR
dll_handle dl4;
const char *libnames4[]={"Xrandr",NULL};
#endif
Status (*xit)(void);
int *_Xdebug;
......@@ -505,44 +515,90 @@ int x_init(void)
xp_dlclose(dl);
return(-1);
}
if((x11.XTranslateCoordinates=xp_dlsym(dl,XTranslateCoordinates))==NULL) {
xp_dlclose(dl);
return(-1);
}
#ifdef WITH_XRENDER
xrender_found = true;
if ((dl2 = xp_dlopen(libnames2,RTLD_LAZY,7)) == NULL) {
if ((dl2 = xp_dlopen(libnames2,RTLD_LAZY,1)) == NULL) {
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderFindStandardFormat = xp_dlsym(dl2, XRenderFindStandardFormat)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderCreatePicture = xp_dlsym(dl2, XRenderCreatePicture)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderFreePicture = xp_dlsym(dl2, XRenderFreePicture)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderSetPictureTransform = xp_dlsym(dl2, XRenderSetPictureTransform)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderComposite = xp_dlsym(dl2, XRenderComposite)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderFindVisualFormat = xp_dlsym(dl2, XRenderFindVisualFormat)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderQueryVersion = xp_dlsym(dl2, XRenderQueryVersion)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
if (xrender_found && ((x11.XRenderSetPictureFilter = xp_dlsym(dl2, XRenderSetPictureFilter)) == NULL)) {
xp_dlclose(dl);
xp_dlclose(dl2);
xrender_found = false;
}
#endif
#ifdef WITH_XINERAMA
xinerama_found = true;
if ((dl3 = xp_dlopen(libnames3,RTLD_LAZY,1)) == NULL) {
xp_dlclose(dl3);
xinerama_found = false;
}
if (xinerama_found && ((x11.XineramaQueryVersion = xp_dlsym(dl3, XineramaQueryVersion)) == NULL)) {
xp_dlclose(dl3);
xinerama_found = false;
}
if (xinerama_found && ((x11.XineramaQueryScreens = xp_dlsym(dl3, XineramaQueryScreens)) == NULL)) {
xp_dlclose(dl3);
xinerama_found = false;
}
#endif
#ifdef WITH_XRANDR
xrandr_found = true;
if ((dl4 = xp_dlopen(libnames4,RTLD_LAZY,2)) == NULL) {
xp_dlclose(dl4);
xrandr_found = false;
}
if (xinerama_found && ((x11.XRRQueryVersion = xp_dlsym(dl4, XRRQueryVersion)) == NULL)) {
xp_dlclose(dl4);
xrandr_found = false;
}
if (xinerama_found && ((x11.XRRGetScreenResources = xp_dlsym(dl4, XRRGetScreenResources)) == NULL)) {
xp_dlclose(dl4);
xrandr_found = false;
}
if (xinerama_found && ((x11.XRRGetCrtcInfo = xp_dlsym(dl4, XRRGetCrtcInfo)) == NULL)) {
xp_dlclose(dl4);
xrandr_found = false;
}
if (xinerama_found && ((x11.XRRFreeCrtcInfo = xp_dlsym(dl4, XRRFreeCrtcInfo)) == NULL)) {
xp_dlclose(dl4);
xrandr_found = false;
}
if (xinerama_found && ((x11.XRRFreeScreenResources = xp_dlsym(dl4, XRRFreeScreenResources)) == NULL)) {
xp_dlclose(dl4);
xrandr_found = false;
}
#endif
setlocale(LC_ALL, "");
x11.XSetLocaleModifiers("@im=none");
......
......@@ -57,6 +57,8 @@ int terminate = 0;
Atom copybuf_format;
Atom pastebuf_format;
bool xrender_found;
bool xinerama_found;
bool xrandr_found;
bool x_internal_scaling = true;
/*
......@@ -95,6 +97,7 @@ static Pixmap xrender_pm = None;
static Picture xrender_src_pict = None;
static Picture xrender_dst_pict = None;
#endif
static bool fullscreen;
/* Array of Graphics Contexts */
static GC gc;
......@@ -215,6 +218,128 @@ static struct {
{ 0x8600, 0x5888, 0x8a00, 0x8c00 }, /* key 88 - F12 */
};
static bool
fullscreen_geometry(int *x_org, int *y_org, int *width, int *height)
{
Window root;
Window cr;
uint64_t dummy;
unsigned int rw, rh;
int wx, wy;
#if defined(WITH_XRANDR) || defined(WITH_XINERAMA)
int cx, cy;
#endif
#ifdef WITH_XRANDR
static XRRScreenResources *xrrsr = NULL;
XRRCrtcInfo *xrrci = NULL;
int searched = 0;
bool found;
#endif
#ifdef WITH_XINERAMA
int i;
int nscrn;
XineramaScreenInfo *xsi;
#endif
if (win == 0)
return false;
if (x11.XGetGeometry(dpy, win, (void *)&root, &wx, &wy, &rw, &rh, (void *)&dummy, (void *)&dummy) == 0)
return false;
#if defined(WITH_XRANDR) || defined(WITH_XINERAMA)
x11.XTranslateCoordinates(dpy, win, root, wx, wy, &cx, &cy, &cr);
cx += rw / 2;
cy += rh / 2;
#endif
#ifdef WITH_XRANDR
// We likely don't actually need Ximerama... this is always better and almost certainly present
if (xrandr_found) {
searched = 0;
found = false;
while (searched < 10 && found == false) {
searched++;
if (xrrsr == NULL)
xrrsr = x11.XRRGetScreenResources(dpy, root);
if (xrrsr == NULL)
break;
for (i = 0; i < xrrsr->ncrtc; i++) {
if (xrrci != NULL)
x11.XRRFreeCrtcInfo(xrrci);
xrrci = x11.XRRGetCrtcInfo(dpy, xrrsr, xrrsr->crtcs[i]);
if (xrrci == NULL) {
x11.XRRFreeScreenResources(xrrsr);
xrrsr = NULL;
break;
}
if (cx >= xrrci->x && cx < xrrci->x + xrrci->width
&& cy >= xrrci->y && cy < xrrci->y + xrrci->height) {
found = true;
break;
}
}
}
if (xrrsr != NULL && !found) {
if (xrrci != NULL)
x11.XRRFreeCrtcInfo(xrrci);
xrrci = x11.XRRGetCrtcInfo(dpy, xrrsr, xrrsr->crtcs[0]);
if (xrrci != NULL)
found = true;
}
if (found) {
if (x_org)
*x_org = xrrci->x;
if (y_org)
*y_org = xrrci->y;
if (width)
*width = xrrci->width;
if (height)
*height = xrrci->height;
if (xrrci != NULL)
x11.XRRFreeCrtcInfo(xrrci);
return true;
}
if (xrrci != NULL)
x11.XRRFreeCrtcInfo(xrrci);
}
#endif
#ifdef WITH_XINERAMA
if (xinerama_found) {
// NOTE: Xinerama is limited to a short for the entire screen dimensions.
if ((xsi = x11.XineramaQueryScreens(dpy, &nscrn)) != NULL && nscrn != 0) {
for (i = 0; i < nscrn; i++) {
if (cx >= xsi[i].x_org && cx < xsi[i].x_org + xsi[i].width
&& cy >= xsi[i].y_org && cy < xsi[i].y_org + xsi[i].height) {
break;
}
}
if (i == nscrn)
i = 0;
if (x_org)
*x_org = xsi[i].x_org;
if (y_org)
*y_org = xsi[i].y_org;
if (width)
*width = xsi[i].width;
if (height)
*height = xsi[i].height;
x11.XFree(xsi);
return true;
}
}
#endif
if (x_org)
*x_org = 0;
if (y_org)
*y_org = 0;
if (width)
*width = rw;
if (height)
*height = rh;
return true;
}
static bool
x11_get_maxsize(int *w, int *h)
{
......@@ -227,12 +352,14 @@ x11_get_maxsize(int *w, int *h)
unsigned long nir;
unsigned long bytes_left = 4;
Window root = DefaultRootWindow(dpy);
unsigned int rw, rh;
uint64_t dummy;
unsigned char *prop;
if (dpy == NULL)
return false;
if (fullscreen) {
return fullscreen_geometry(NULL, NULL, w, h);
}
else {
// First, try to get _NET_WORKAREA...
if (x11.workarea == None) {
x11.workarea = x11.XInternAtom(dpy, "_NET_WORKAREA", True);
......@@ -257,16 +384,13 @@ x11_get_maxsize(int *w, int *h)
x11.XFree(prop);
}
}
}
// Couldn't get work area, get size of root window instead. :(
// Couldn't get work area, get size of screen instead. :(
if (maxw == 0 || maxh == 0) {
if (x11.XGetGeometry(dpy, root, (void *)&dummy, (void *)&dummy, (void *)&dummy, &rw, &rh, (void *)&dummy, (void *)&dummy)) {
if (rw > maxw)
maxw = rw;
if (rh > maxh)
maxh = rh;
}
fullscreen_geometry(NULL, NULL, &maxw, &maxh);
}
if (maxw != 0 && maxh != 0) {
*w = maxw;
*h = maxh;
......@@ -279,6 +403,7 @@ static void
resize_pictures(void)
{
#ifdef WITH_XRENDER
if (xrender_found) {
if (xrender_pf == NULL)
xrender_pf = x11.XRenderFindStandardFormat(dpy, PictStandardRGB24);
if (xrender_pf == NULL)
......@@ -307,6 +432,7 @@ resize_pictures(void)
}};
pthread_mutex_unlock(&vstatlock);
x11.XRenderSetPictureTransform(dpy, xrender_src_pict, &transform_matrix);
}
#endif
}
......@@ -533,6 +659,14 @@ static int init_window()
if (xrender_found && x11.XRenderQueryVersion(dpy, &major, &minor) == 0)
xrender_found = false;
#endif
#ifdef WITH_XINERAMA
if (xinerama_found && x11.XineramaQueryVersion(dpy, &major, &minor) == 0)
xinerama_found = false;
#endif
#ifdef WITH_XRANDR
if (xrandr_found && x11.XRRQueryVersion(dpy, &major, &minor) == 0)
xrandr_found = false;
#endif
xfd = ConnectionNumber(dpy);
x11.utf8 = x11.XInternAtom(dpy, "UTF8_STRING", False);
......@@ -782,6 +916,10 @@ local_draw_rect(struct rectlist *rect)
// Scale...
pthread_mutex_lock(&vstatlock);
if (x_cvstat.winwidth != vstat.winwidth || x_cvstat.winheight != vstat.winheight) {
pthread_mutex_unlock(&vstatlock);
return;
}
bitmap_get_scaled_win_size(vstat.scaling, &w, &h, vstat.winwidth, vstat.winheight);
pthread_mutex_unlock(&vstatlock);
if (w < rect->rect.width || h < rect->rect.height) {
......@@ -903,7 +1041,7 @@ local_draw_rect(struct rectlist *rect)
}
if (x_internal_scaling || xrender_found == false) {
if (last == NULL)
x11.XPutImage(dpy, win, gc, xim, 0, 0, xoff, yoff, source->w, source->h);
x11.XPutImage(dpy, win, gc, xim, 0, 0, xoff, yoff, cleft, ctop);
else {
release_buffer(last);
last = NULL;
......@@ -1331,6 +1469,9 @@ static int x11_event(XEvent *ev)
case XK_Return:
case XK_KP_Enter:
if (ev->xkey.state & Mod1Mask) {
// ALT-Enter, toggle full-screen
}
scan = 28;
goto docode;
......
......@@ -9,6 +9,12 @@
#ifdef WITH_XRENDER
#include <X11/extensions/Xrender.h>
#endif
#ifdef WITH_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef WITH_XRANDR
#include <X11/extensions/Xrandr.h>
#endif
enum x11_local_events {
X11_LOCAL_SETMODE
......@@ -106,6 +112,7 @@ struct x11 {
Status (*XGetGeometry)(Display *, Drawable, Window *, int *, int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *);
XWMHints *(*XGetWMHints)(Display *, Window);
int (*XSetWMHints)(Display *, Window, XWMHints *);
Bool (*XTranslateCoordinates)(Display *, Window, Window, int, int, int *, int *, Window *);
#ifndef DefaultDepth
int (*DefaultDepth)(Display *, int);
#endif
......@@ -121,6 +128,17 @@ struct x11 {
XRenderPictFormat *(*XRenderFindVisualFormat)(Display *dpy, _Xconst Visual *visual);
Status (*XRenderQueryVersion)(Display *, int *, int *);
void (*XRenderSetPictureFilter)(Display *, Picture, const char *, XFixed *, int);
#endif
#ifdef WITH_XINERAMA
Bool (*XineramaQueryVersion)(Display *, int *, int *);
XineramaScreenInfo *(*XineramaQueryScreens)(Display *, int *);
#endif
#ifdef WITH_XRANDR
Bool (*XRRQueryVersion)(Display *, int *, int *);
XRRScreenResources *(*XRRGetScreenResources)(Display *, Window);
XRRCrtcInfo *(*XRRGetCrtcInfo)(Display *, XRRScreenResources *, RRCrtc);
void (*XRRFreeCrtcInfo)(XRRCrtcInfo *crtcInfo);
void (*XRRFreeScreenResources)(XRRScreenResources *resources);
#endif
Atom utf8;
Atom targets;
......@@ -148,6 +166,8 @@ extern int x11_window_ypos;
extern int x11_initialized;
extern struct video_stats x_cvstat;
extern bool xrender_found;
extern bool xinerama_found;
extern bool xrandr_found;
extern bool x_internal_scaling;
void x11_event_thread(void *args);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment