diff --git a/include/boo/IWindow.hpp b/include/boo/IWindow.hpp index 942319a..ce05870 100644 --- a/include/boo/IWindow.hpp +++ b/include/boo/IWindow.hpp @@ -86,7 +86,7 @@ enum EModifierKey MKEY_SHIFT = 1<<3, MKEY_COMMAND = 1<<4 }; - + class IWindowCallback { public: @@ -119,7 +119,6 @@ public: virtual void modKeyDown(EModifierKey mod, bool isRepeat) {(void)mod;(void)isRepeat;} virtual void modKeyUp(EModifierKey mod) {(void)mod;} - }; enum ETouchType @@ -129,6 +128,16 @@ enum ETouchType TOUCH_TRACKPAD = 2 }; +enum EWindowStyle +{ + STYLE_NONE = 0, + STYLE_TITLEBAR = 1<<0, + STYLE_RESIZE = 1<<1, + STYLE_CLOSE = 1<<2, + + STYLE_DEFAULT = STYLE_TITLEBAR | STYLE_RESIZE | STYLE_CLOSE +}; + class IWindow { public: @@ -172,6 +181,8 @@ public: virtual IGraphicsCommandQueue* getCommandQueue()=0; virtual IGraphicsDataFactory* getDataFactory()=0; + virtual void setStyle(EWindowStyle style)=0; + virtual EWindowStyle getStyle() const=0; /* Creates a new context on current thread!! Call from client loading thread */ virtual IGraphicsDataFactory* getLoadContextDataFactory()=0; diff --git a/lib/x11/WindowWayland.cpp b/lib/x11/WindowWayland.cpp index 2f1812e..c43cca1 100644 --- a/lib/x11/WindowWayland.cpp +++ b/lib/x11/WindowWayland.cpp @@ -115,7 +115,7 @@ struct WindowWayland : IWindow std::string getTitle() { - + return ""; } void setTitle(const std::string& title) @@ -150,12 +150,20 @@ struct WindowWayland : IWindow float getVirtualPixelFactor() const { - + return 0; } + void setStyle(EWindowStyle /*style*/) + {} + + EWindowStyle getStyle() const + { + return STYLE_NONE; + } + bool isFullscreen() const { - + return false; } void setFullscreen(bool fs) @@ -169,12 +177,12 @@ struct WindowWayland : IWindow uintptr_t getPlatformHandle() const { - + return 0; } ETouchType getTouchType() const { - + return TOUCH_NONE; } diff --git a/lib/x11/WindowXlib.cpp b/lib/x11/WindowXlib.cpp index 736a5db..2674a8d 100644 --- a/lib/x11/WindowXlib.cpp +++ b/lib/x11/WindowXlib.cpp @@ -18,11 +18,27 @@ #include #include #include +#include #define REF_DPMM 3.7824 /* 96 DPI */ #define FS_ATOM "_NET_WM_STATE_FULLSCREEN" -#include +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) + +#define MWM_DECOR_BORDER (1L<<1) +#define MWM_DECOR_RESIZEH (1L<<2) +#define MWM_DECOR_TITLE (1L<<3) +#define MWM_DECOR_MENU (1L<<4) +#define MWM_DECOR_MINIMIZE (1L<<5) +#define MWM_DECOR_MAXIMIZE (1L<<6) + +#define MWM_FUNC_RESIZE (1L<<1) +#define MWM_FUNC_MOVE (1L<<2) +#define MWM_FUNC_MINIMIZE (1L<<3) +#define MWM_FUNC_MAXIMIZE (1L<<4) +#define MWM_FUNC_CLOSE (1L<<5) + typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; @@ -391,6 +407,9 @@ class WindowXlib : public IWindow float m_pixelFactor; bool m_inFs = false; + /* Cached window style */ + EWindowStyle m_styleFlags; + public: WindowXlib(const std::string& title, @@ -474,6 +493,8 @@ public: XMapWindow(m_xDisp, m_windowId); XFlush(m_xDisp); + setStyle(STYLE_DEFAULT); + m_gfxCtx.initializeContext(); } @@ -574,13 +595,14 @@ public: bool isFullscreen() const { + return m_inFs; unsigned long nitems; Atom actualType; int actualFormat; unsigned long bytes; Atom* vals = nullptr; bool fullscreen = false; - if (XGetWindowProperty(m_xDisp, m_windowId, XInternAtom(m_xDisp, "_NET_WM_STATE", True), 0, ~0l, False, + if (XGetWindowProperty(m_xDisp, m_windowId, S_ATOMS->m_netwmState, 0, ~0l, False, XA_ATOM, &actualType, &actualFormat, &nitems, &bytes, (unsigned char**)&vals) == Success) { for (int i=0 ; im_motifWmHints) + { + wmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS; + if (style & STYLE_TITLEBAR) + { + wmHints.decorations |= MWM_DECOR_BORDER | MWM_DECOR_TITLE | MWM_DECOR_MINIMIZE | MWM_DECOR_MENU; + wmHints.functions |= MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE; + } + if (style & STYLE_RESIZE) + { + wmHints.decorations |= MWM_DECOR_MAXIMIZE | MWM_DECOR_RESIZEH; + wmHints.functions |= MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE; + } + + if (style & STYLE_CLOSE) + wmHints.functions |= MWM_FUNC_CLOSE; + + XChangeProperty(m_xDisp, m_windowId, S_ATOMS->m_motifWmHints, S_ATOMS->m_motifWmHints, 32, PropModeReplace, (unsigned char*)&wmHints, 5); + } + + m_styleFlags = style; + } + + EWindowStyle getStyle() const + { + return m_styleFlags; + } + void setFullscreen(bool fs) { if (fs == m_inFs) @@ -605,14 +666,17 @@ public: XEvent fsEvent = {0}; fsEvent.xclient.type = ClientMessage; + fsEvent.xclient.serial = 0; + fsEvent.xclient.send_event = True; fsEvent.xclient.window = m_windowId; - fsEvent.xclient.message_type = XInternAtom(m_xDisp, "_NET_WM_STATE", False); + fsEvent.xclient.message_type = S_ATOMS->m_netwmState; fsEvent.xclient.format = 32; fsEvent.xclient.data.l[0] = fs; - fsEvent.xclient.data.l[1] = XInternAtom(m_xDisp, "_NET_WM_STATE_FULLSCREEN", False); + fsEvent.xclient.data.l[1] = S_ATOMS->m_netwmStateFullscreen; fsEvent.xclient.data.l[2] = 0; XSendEvent(m_xDisp, DefaultRootWindow(m_xDisp), False, StructureNotifyMask | SubstructureRedirectMask, (XEvent*)&fsEvent); + m_inFs = fs; } @@ -1014,7 +1078,6 @@ public: return m_gfxCtx.getLoadContextDataFactory(); } - bool _isWindowMapped() { XWindowAttributes attr; diff --git a/test/main.cpp b/test/main.cpp index 2950726..7074b7c 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -125,6 +125,7 @@ public: struct CTestWindowCallback : IWindowCallback { + bool m_fullscreenToggleRequested = false; SWindowRect m_lastRect; bool m_rectDirty = false; @@ -149,7 +150,7 @@ struct CTestWindowCallback : IWindowCallback } void scroll(const SWindowCoord& coord, const SScrollDelta& scroll) { - fprintf(stderr, "Mouse Scroll (%f,%f) (%f,%f)\n", coord.norm[0], coord.norm[1], scroll.delta[0], scroll.delta[1]); + //fprintf(stderr, "Mouse Scroll (%f,%f) (%f,%f)\n", coord.norm[0], coord.norm[1], scroll.delta[0], scroll.delta[1]); } void touchDown(const STouchCoord& coord, uintptr_t tid) @@ -175,7 +176,8 @@ struct CTestWindowCallback : IWindowCallback } void specialKeyDown(ESpecialKey key, EModifierKey mods, bool isRepeat) { - + if (key == boo::KEY_ENTER && (mods & boo::MKEY_ALT)) + m_fullscreenToggleRequested = true; } void specialKeyUp(ESpecialKey key, EModifierKey mods) { @@ -373,6 +375,12 @@ struct TestApplicationCallback : IApplicationCallback windowCallback.m_rectDirty = false; } + if (windowCallback.m_fullscreenToggleRequested) + { + mainWindow->setFullscreen(!mainWindow->isFullscreen()); + windowCallback.m_fullscreenToggleRequested = false; + } + gfxQ->setRenderTarget(m_renderTarget); SWindowRect r = windowCallback.m_lastRect; r.location[0] = 0;