diff --git a/source/Platform/Unix/X11Display.cpp b/source/Platform/Unix/X11Display.cpp index 8b87b2e..d255d58 100644 --- a/source/Platform/Unix/X11Display.cpp +++ b/source/Platform/Unix/X11Display.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#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; } } diff --git a/source/Platform/Unix/X11Display.h b/source/Platform/Unix/X11Display.h index ae2d327..2c2ca79 100644 --- a/source/Platform/Unix/X11Display.h +++ b/source/Platform/Unix/X11Display.h @@ -7,6 +7,7 @@ #include #include #include +#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