Commit 8803ce9d authored by Erwan Tulou's avatar Erwan Tulou

skins(x11): use EWMH when possible (especially for fullscreen)

parent 2093cfa7
...@@ -240,6 +240,9 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ), ...@@ -240,6 +240,9 @@ X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
// Move it outside the screen to avoid seeing it in workspace selector // Move it outside the screen to avoid seeing it in workspace selector
XMoveWindow( m_pDisplay, m_mainWindow, -10, -10 ); XMoveWindow( m_pDisplay, m_mainWindow, -10, -10 );
// test EWMH capabilities
testEWMH();
} }
} }
...@@ -253,6 +256,59 @@ X11Display::~X11Display() ...@@ -253,6 +256,59 @@ X11Display::~X11Display()
} }
void X11Display::testEWMH()
{
int i_ret, i_format;
unsigned long i_items, i_bytesafter;
union { Atom *p_atom; unsigned char *p_char; } p_args;
p_args.p_atom = NULL;
m_net_wm_supported = XInternAtom( m_pDisplay, "_NET_SUPPORTED", False );
msg_Dbg( getIntf(), "EWMH: supported %d", m_net_wm_supported != None ? 1 : 0 );
if( m_net_wm_supported == None )
return;
i_ret = XGetWindowProperty( m_pDisplay, DefaultRootWindow( m_pDisplay ),
m_net_wm_supported,
0, 16384, False, AnyPropertyType,
&m_net_wm_supported,
&i_format, &i_items, &i_bytesafter,
(unsigned char **)&p_args );
if( i_ret != Success || i_items == 0 )
return; /* Not supported */
#define TEST_EWMH( name, value ) \
{\
name = XInternAtom( m_pDisplay, value, False );\
int i;\
for( i = 0; i < i_items; i++ )\
{\
if( p_args.p_atom[i] == name ) break;\
}\
if( i == i_items )\
{\
msg_Dbg( getIntf(), "%s support: no", value );\
name = None;\
}\
else\
msg_Dbg( getIntf(), "%s support: yes", value );\
}
TEST_EWMH( m_net_wm_state, "_NET_WM_STATE" )
TEST_EWMH( m_net_wm_state_fullscreen, "_NET_WM_STATE_FULLSCREEN" )
TEST_EWMH( m_net_wm_stays_on_top, "_NET_WM_STATE_STAYS_ON_TOP" )
TEST_EWMH( m_net_wm_state_above, "_NET_WM_STATE_ABOVE" )
TEST_EWMH( m_net_wm_window_opacity, "_NET_WM_WINDOW_OPACITY" )
#undef TEST_EWMH
XFree( p_args.p_atom );
}
void X11Display::getShifts( uint32_t mask, int &rLeftShift, int &rRightShift ) void X11Display::getShifts( uint32_t mask, int &rLeftShift, int &rRightShift )
{ {
for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ ) for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
#define X11_DISPLAY_HPP #define X11_DISPLAY_HPP
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "../src/skin_common.hpp" #include "../src/skin_common.hpp"
// Helper macros // Helper macros
...@@ -35,6 +35,14 @@ ...@@ -35,6 +35,14 @@
#define XPIXELSIZE m_rDisplay.getPixelSize() #define XPIXELSIZE m_rDisplay.getPixelSize()
#define XGC m_rDisplay.getGC() #define XGC m_rDisplay.getGC()
#define NET_WM_SUPPORTED m_rDisplay.m_net_wm_supported
#define NET_WM_STATE m_rDisplay.m_net_wm_state
#define NET_WM_STATE_FULLSCREEN m_rDisplay.m_net_wm_state_fullscreen
#define NET_WM_STATE_ABOVE m_rDisplay.m_net_wm_state_above
#define NET_WM_STAYS_ON_TOP m_rDisplay.m_net_wm_stays_on_top
#define NET_WM_WINDOW_OPACITY m_rDisplay.m_net_wm_window_opacity
/// Class for encapsulation of a X11 Display /// Class for encapsulation of a X11 Display
class X11Display: public SkinObject class X11Display: public SkinObject
...@@ -75,7 +83,19 @@ public: ...@@ -75,7 +83,19 @@ public:
Window getMainWindow() const { return m_mainWindow; } Window getMainWindow() const { return m_mainWindow; }
//XXX //XXX
Window m_voutWindow; ///Window m_voutWindow;
/// EWMH spec
Atom m_net_wm_supported;
Atom m_net_wm_state;
Atom m_net_wm_state_above;
Atom m_net_wm_state_fullscreen;
Atom m_net_wm_stays_on_top;
Atom m_net_wm_window_opacity;
/// test EWMH capabilities
void testEWMH();
private: private:
/// Dummy parent window for the task bar /// Dummy parent window for the task bar
...@@ -140,6 +160,7 @@ private: ...@@ -140,6 +160,7 @@ private:
/// 24/32 bpp LSB first version of putPixel /// 24/32 bpp LSB first version of putPixel
void putPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b, void putPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const; uint8_t a ) const;
}; };
#endif #endif
...@@ -54,9 +54,13 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow, ...@@ -54,9 +54,13 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
attr.event_mask = ExposureMask | StructureNotifyMask; attr.event_mask = ExposureMask | StructureNotifyMask;
attr.background_pixel = BlackPixel( XDISPLAY, i_screen ); attr.background_pixel = BlackPixel( XDISPLAY, i_screen );
attr.backing_store = Always; attr.backing_store = Always;
valuemask = CWBackingStore | CWBackPixel | CWEventMask;
if( NET_WM_STATE_FULLSCREEN == None )
{
attr.override_redirect = True; attr.override_redirect = True;
valuemask = CWBackingStore | CWOverrideRedirect | valuemask = valuemask | CWOverrideRedirect;
CWBackPixel | CWEventMask; }
name_type = "Fullscreen"; name_type = "Fullscreen";
} }
...@@ -177,10 +181,10 @@ void X11Window::reparent( void* OSHandle, int x, int y, int w, int h ) ...@@ -177,10 +181,10 @@ void X11Window::reparent( void* OSHandle, int x, int y, int w, int h )
Window new_parent = Window new_parent =
OSHandle ? (Window) OSHandle : DefaultRootWindow( XDISPLAY ); OSHandle ? (Window) OSHandle : DefaultRootWindow( XDISPLAY );
XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
if( w && h ) if( w && h )
XResizeWindow( XDISPLAY, m_wnd, w, h ); XResizeWindow( XDISPLAY, m_wnd, w, h );
XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
m_wnd_parent = new_parent; m_wnd_parent = new_parent;
} }
...@@ -193,6 +197,12 @@ void X11Window::show() const ...@@ -193,6 +197,12 @@ void X11Window::show() const
XLowerWindow( XDISPLAY, m_wnd ); XLowerWindow( XDISPLAY, m_wnd );
XMapWindow( XDISPLAY, m_wnd ); XMapWindow( XDISPLAY, m_wnd );
} }
else if( m_type == GenericWindow::FullscreenWindow )
{
XMapRaised( XDISPLAY, m_wnd );
setFullscreen();
// toggleOnTop( true );
}
else else
{ {
XMapRaised( XDISPLAY, m_wnd ); XMapRaised( XDISPLAY, m_wnd );
...@@ -206,7 +216,6 @@ void X11Window::hide() const ...@@ -206,7 +216,6 @@ void X11Window::hide() const
XUnmapWindow( XDISPLAY, m_wnd ); XUnmapWindow( XDISPLAY, m_wnd );
} }
void X11Window::moveResize( int left, int top, int width, int height ) const void X11Window::moveResize( int left, int top, int width, int height ) const
{ {
if( width && height ) if( width && height )
...@@ -224,96 +233,80 @@ void X11Window::raise() const ...@@ -224,96 +233,80 @@ void X11Window::raise() const
void X11Window::setOpacity( uint8_t value ) const void X11Window::setOpacity( uint8_t value ) const
{ {
Atom opaq = XInternAtom(XDISPLAY, "_NET_WM_WINDOW_OPACITY", False); if( NET_WM_WINDOW_OPACITY == None )
return;
if( 255==value ) if( 255==value )
XDeleteProperty(XDISPLAY, m_wnd, opaq); XDeleteProperty(XDISPLAY, m_wnd, NET_WM_WINDOW_OPACITY);
else else
{ {
uint32_t opacity = value * ((uint32_t)-1/255); uint32_t opacity = value * ((uint32_t)-1/255);
XChangeProperty(XDISPLAY, m_wnd, opaq, XA_CARDINAL, 32, XChangeProperty(XDISPLAY, m_wnd, NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
PropModeReplace, (unsigned char *) &opacity, 1L); PropModeReplace, (unsigned char *) &opacity, 1L);
} }
XSync( XDISPLAY, False ); XSync( XDISPLAY, False );
} }
void X11Window::toggleOnTop( bool onTop ) const void X11Window::setFullscreen( ) const
{ {
int i_ret, i_format; if( NET_WM_STATE_FULLSCREEN != None )
unsigned long i, i_items, i_bytesafter;
Atom net_wm_supported, net_wm_state, net_wm_state_on_top,net_wm_state_above;
union { Atom *p_atom; unsigned char *p_char; } p_args;
p_args.p_atom = NULL;
net_wm_supported = XInternAtom( XDISPLAY, "_NET_SUPPORTED", False );
i_ret = XGetWindowProperty( XDISPLAY, DefaultRootWindow( XDISPLAY ),
net_wm_supported,
0, 16384, False, AnyPropertyType,
&net_wm_supported,
&i_format, &i_items, &i_bytesafter,
(unsigned char **)&p_args );
if( i_ret != Success || i_items == 0 ) return; /* Not supported */
net_wm_state = XInternAtom( XDISPLAY, "_NET_WM_STATE", False );
net_wm_state_on_top = XInternAtom( XDISPLAY, "_NET_WM_STATE_STAYS_ON_TOP",
False );
for( i = 0; i < i_items; i++ )
{ {
if( p_args.p_atom[i] == net_wm_state_on_top ) break; XClientMessageEvent event;
} memset( &event, 0, sizeof( XClientMessageEvent ) );
if( i == i_items ) event.type = ClientMessage;
{ /* use _NET_WM_STATE_ABOVE if window manager event.message_type = NET_WM_STATE;
* doesn't handle _NET_WM_STATE_STAYS_ON_TOP */ event.display = XDISPLAY;
event.window = m_wnd;
event.format = 32;
event.data.l[ 0 ] = 1;
event.data.l[ 1 ] = NET_WM_STATE_FULLSCREEN;
net_wm_state_above = XInternAtom( XDISPLAY, "_NET_WM_STATE_ABOVE", XSendEvent( XDISPLAY,
False); DefaultRootWindow( XDISPLAY ),
for( i = 0; i < i_items; i++ ) False, SubstructureNotifyMask|SubstructureRedirectMask,
{ (XEvent*)&event );
if( p_args.p_atom[i] == net_wm_state_above ) break;
} }
}
XFree( p_args.p_atom );
if( i == i_items )
return; /* Not supported */
void X11Window::toggleOnTop( bool onTop ) const
{
if( NET_WM_STAYS_ON_TOP != None )
{
/* Switch "on top" status */ /* Switch "on top" status */
XClientMessageEvent event; XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) ); memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage; event.type = ClientMessage;
event.message_type = net_wm_state; event.message_type = NET_WM_STATE;
event.display = XDISPLAY; event.display = XDISPLAY;
event.window = m_wnd; event.window = m_wnd;
event.format = 32; event.format = 32;
event.data.l[ 0 ] = onTop; /* set property */ event.data.l[ 0 ] = onTop; /* set property */
event.data.l[ 1 ] = net_wm_state_above; event.data.l[ 1 ] = NET_WM_STAYS_ON_TOP;
XSendEvent( XDISPLAY, DefaultRootWindow( XDISPLAY ), XSendEvent( XDISPLAY, DefaultRootWindow( XDISPLAY ),
False, SubstructureRedirectMask, (XEvent*)&event ); False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent*)&event );
return;
} }
else if( NET_WM_STATE_ABOVE != None )
XFree( p_args.p_atom ); {
/* Switch "above" state */
/* Switch "on top" status */
XClientMessageEvent event; XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) ); memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage; event.type = ClientMessage;
event.message_type = net_wm_state; event.message_type = NET_WM_STATE;
event.display = XDISPLAY; event.display = XDISPLAY;
event.window = m_wnd; event.window = m_wnd;
event.format = 32; event.format = 32;
event.data.l[ 0 ] = onTop; /* set property */ event.data.l[ 0 ] = onTop; /* set property */
event.data.l[ 1 ] = net_wm_state_on_top; event.data.l[ 1 ] = NET_WM_STATE_ABOVE;
XSendEvent( XDISPLAY, DefaultRootWindow( XDISPLAY ), XSendEvent( XDISPLAY, DefaultRootWindow( XDISPLAY ),
False, SubstructureRedirectMask, (XEvent*)&event ); False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent*)&event );
}
} }
#endif #endif
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#define X11_WINDOW_HPP #define X11_WINDOW_HPP
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "../src/generic_window.hpp" #include "../src/generic_window.hpp"
#include "../src/os_window.hpp" #include "../src/os_window.hpp"
...@@ -75,6 +76,8 @@ public: ...@@ -75,6 +76,8 @@ public:
/// reparent the window /// reparent the window
void reparent( void* OSHandle, int x, int y, int w, int h ); void reparent( void* OSHandle, int x, int y, int w, int h );
void setFullscreen() const;
private: private:
/// X11 display /// X11 display
X11Display &m_rDisplay; X11Display &m_rDisplay;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment