1
0
Fork 0

source/Platform/Unix/X11Display.cpp: implement fullscreen somewhat correctly :)

This commit is contained in:
Henrik Hautakoski 2023-08-02 06:01:33 +02:00
parent 186a6e0f14
commit 2cf035089b
2 changed files with 82 additions and 1 deletions

View file

@ -2,6 +2,8 @@
#include <cstring>
#include <Spectre/System/Log.h>
#include <Spectre/Graphics/Image.h>
#include <X11/Xatom.h>
#include "XRandR.h"
#include "X11WindowEventHandler.h"
#include "Xlib.h"
#include "wm_hints.h"
@ -238,14 +240,75 @@ void X11Display::maximize()
void X11Display::enterFullscreen(DisplayMode mode)
{
if (!XRandR::FindMode(Xlib::getDisplay(), mode.width, mode.height, mode.bpp, &m_fullscreen_mode.size, &m_fullscreen_mode.rate)) {
Log::warn("X11: Failed to find a mode");
return;
}
toggleFullscreen(true);
}
void X11Display::toggleFullscreen(bool enable)
{
::Display* disp = Xlib::getDisplay();
::Window root;
::XRRScreenConfiguration *conf;
XRandR::VideoMode *mode = &m_desktop_mode;
root = RootWindow(disp, 0);
conf = XRRGetScreenInfo(disp, root);
if (enable) {
if (m_desktop_mode.rate < 1) {
Rotation r;
m_desktop_mode.rate = XRRConfigCurrentRate(conf);
m_desktop_mode.size = XRRConfigCurrentConfiguration(conf, &r);
}
mode = &m_fullscreen_mode;
}
wm_fullscreen(enable);
XRRSetScreenConfigAndRate(disp, conf, root, mode->size, RR_Rotate_0, mode->rate, CurrentTime);
}
void X11Display::exitFullscreen()
{
if (m_fullscreen_mode.rate > 0) {
toggleFullscreen(false);
m_fullscreen_mode.rate = 0;
m_fullscreen_mode.size = 0;
m_desktop_mode.rate = 0;
m_desktop_mode.size = 0;
}
}
#define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
#define _NET_WM_STATE_ADD 1 /* add/set property */
void X11Display::wm_fullscreen(bool enabled) {
::Display* disp = sp::Xlib::getDisplay();
XEvent xev;
Atom wm_state = sp::Xlib::getAtom("_NET_WM_STATE", False);
Atom wm_fs = sp::Xlib::getAtom("_NET_WM_STATE_FULLSCREEN", False);
memset(&xev, 0, sizeof(xev));
xev.type = ClientMessage;
xev.xclient.window = m_win;
xev.xclient.message_type = wm_state;
xev.xclient.format = 32;
xev.xclient.data.l[0] = enabled ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
xev.xclient.data.l[1] = wm_fs;
xev.xclient.data.l[2] = 0;
::XSendEvent(disp, ::XDefaultRootWindow(disp), False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
}
void X11Display::setCaption(const std::string& caption)
{
::XStoreName(Xlib::getDisplay(), m_win, caption.c_str());
@ -329,10 +392,19 @@ void X11Display::processEvent(const ::XEvent& event)
case FocusIn:
Log::debug("X11: FocusIn");
_priv::focused_display = this;
if (m_fullscreen_mode.rate > 0) {
toggleFullscreen(true);
}
break;
case FocusOut:
Log::debug("X11: FocusOut");
_priv::focused_display = NULL;
if (m_fullscreen_mode.rate > 0) {
toggleFullscreen(false);
minimize();
}
break;
}
}

View file

@ -7,6 +7,7 @@
#include <X11/Xos.h>
#include <cstdint>
#include <Platform/PlatformDisplay.h>
#include "Xrandr.h"
namespace sp {
@ -62,6 +63,10 @@ protected :
void createHiddenCursor();
void toggleFullscreen(bool enabled);
void wm_fullscreen(bool enabled);
protected :
::Window m_win;
@ -72,6 +77,10 @@ protected :
::Cursor m_cur_last;
Vector2u m_size;
XRandR::VideoMode m_fullscreen_mode;
XRandR::VideoMode m_desktop_mode;
};
} // namespace sp