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 ),
// Move it outside the screen to avoid seeing it in workspace selector
XMoveWindow( m_pDisplay, m_mainWindow, -10, -10 );
// test EWMH capabilities
testEWMH();
}
}
......@@ -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 )
{
for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
......
......@@ -26,7 +26,7 @@
#define X11_DISPLAY_HPP
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "../src/skin_common.hpp"
// Helper macros
......@@ -35,6 +35,14 @@
#define XPIXELSIZE m_rDisplay.getPixelSize()
#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 X11Display: public SkinObject
......@@ -75,7 +83,19 @@ public:
Window getMainWindow() const { return m_mainWindow; }
//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:
/// Dummy parent window for the task bar
......@@ -140,6 +160,7 @@ private:
/// 24/32 bpp LSB first version of putPixel
void putPixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
uint8_t a ) const;
};
#endif
......@@ -54,9 +54,13 @@ X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
attr.event_mask = ExposureMask | StructureNotifyMask;
attr.background_pixel = BlackPixel( XDISPLAY, i_screen );
attr.backing_store = Always;
valuemask = CWBackingStore | CWBackPixel | CWEventMask;
if( NET_WM_STATE_FULLSCREEN == None )
{
attr.override_redirect = True;
valuemask = CWBackingStore | CWOverrideRedirect |
CWBackPixel | CWEventMask;
valuemask = valuemask | CWOverrideRedirect;
}
name_type = "Fullscreen";
}
......@@ -177,10 +181,10 @@ void X11Window::reparent( void* OSHandle, int x, int y, int w, int h )
Window new_parent =
OSHandle ? (Window) OSHandle : DefaultRootWindow( XDISPLAY );
XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
if( w && h )
XResizeWindow( XDISPLAY, m_wnd, w, h );
XReparentWindow( XDISPLAY, m_wnd, new_parent, x, y);
m_wnd_parent = new_parent;
}
......@@ -193,6 +197,12 @@ void X11Window::show() const
XLowerWindow( XDISPLAY, m_wnd );
XMapWindow( XDISPLAY, m_wnd );
}
else if( m_type == GenericWindow::FullscreenWindow )
{
XMapRaised( XDISPLAY, m_wnd );
setFullscreen();
// toggleOnTop( true );
}
else
{
XMapRaised( XDISPLAY, m_wnd );
......@@ -206,7 +216,6 @@ void X11Window::hide() const
XUnmapWindow( XDISPLAY, m_wnd );
}
void X11Window::moveResize( int left, int top, int width, int height ) const
{
if( width && height )
......@@ -224,96 +233,80 @@ void X11Window::raise() 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 )
XDeleteProperty(XDISPLAY, m_wnd, opaq);
XDeleteProperty(XDISPLAY, m_wnd, NET_WM_WINDOW_OPACITY);
else
{
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);
}
XSync( XDISPLAY, False );
}
void X11Window::toggleOnTop( bool onTop ) const
void X11Window::setFullscreen( ) const
{
int i_ret, i_format;
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( NET_WM_STATE_FULLSCREEN != None )
{
if( p_args.p_atom[i] == net_wm_state_on_top ) break;
}
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
if( i == i_items )
{ /* use _NET_WM_STATE_ABOVE if window manager
* doesn't handle _NET_WM_STATE_STAYS_ON_TOP */
event.type = ClientMessage;
event.message_type = NET_WM_STATE;
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",
False);
for( i = 0; i < i_items; i++ )
{
if( p_args.p_atom[i] == net_wm_state_above ) break;
XSendEvent( XDISPLAY,
DefaultRootWindow( XDISPLAY ),
False, SubstructureNotifyMask|SubstructureRedirectMask,
(XEvent*)&event );
}
}
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 */
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage;
event.message_type = net_wm_state;
event.message_type = NET_WM_STATE;
event.display = XDISPLAY;
event.window = m_wnd;
event.format = 32;
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 ),
False, SubstructureRedirectMask, (XEvent*)&event );
return;
False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent*)&event );
}
XFree( p_args.p_atom );
/* Switch "on top" status */
else if( NET_WM_STATE_ABOVE != None )
{
/* Switch "above" state */
XClientMessageEvent event;
memset( &event, 0, sizeof( XClientMessageEvent ) );
event.type = ClientMessage;
event.message_type = net_wm_state;
event.message_type = NET_WM_STATE;
event.display = XDISPLAY;
event.window = m_wnd;
event.format = 32;
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 ),
False, SubstructureRedirectMask, (XEvent*)&event );
False, SubstructureNotifyMask|SubstructureRedirectMask, (XEvent*)&event );
}
}
#endif
......@@ -26,6 +26,7 @@
#define X11_WINDOW_HPP
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include "../src/generic_window.hpp"
#include "../src/os_window.hpp"
......@@ -75,6 +76,8 @@ public:
/// reparent the window
void reparent( void* OSHandle, int x, int y, int w, int h );
void setFullscreen() const;
private:
/// X11 display
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