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 <cstring>
#include <Spectre/System/Log.h> #include <Spectre/System/Log.h>
#include <Spectre/Graphics/Image.h> #include <Spectre/Graphics/Image.h>
#include <X11/Xatom.h>
#include "XRandR.h"
#include "X11WindowEventHandler.h" #include "X11WindowEventHandler.h"
#include "Xlib.h" #include "Xlib.h"
#include "wm_hints.h" #include "wm_hints.h"
@ -238,13 +240,74 @@ void X11Display::maximize()
void X11Display::enterFullscreen(DisplayMode mode) 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() 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) void X11Display::setCaption(const std::string& caption)
{ {
@ -329,10 +392,19 @@ void X11Display::processEvent(const ::XEvent& event)
case FocusIn: case FocusIn:
Log::debug("X11: FocusIn"); Log::debug("X11: FocusIn");
_priv::focused_display = this; _priv::focused_display = this;
if (m_fullscreen_mode.rate > 0) {
toggleFullscreen(true);
}
break; break;
case FocusOut: case FocusOut:
Log::debug("X11: FocusOut"); Log::debug("X11: FocusOut");
_priv::focused_display = NULL; _priv::focused_display = NULL;
if (m_fullscreen_mode.rate > 0) {
toggleFullscreen(false);
minimize();
}
break; break;
} }
} }

View file

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