@ -1,37 +1,24 @@
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				/*
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  Holds  one  embedded  window ,  registers  as  DBus  entry 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  Copyright  ( C )  2015  < davidedmundson @ kde . org >  David  Edmundson 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  This  library  is  free  software ;  you  can  redistribute  it  and / or 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  modify  it  under  the  terms  of  the  GNU  Lesser  General  Public 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  License  as  published  by  the  Free  Software  Foundation ;  either 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  version  2.1  of  the  License ,  or  ( at  your  option )  any  later  version . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  This  library  is  distributed  in  the  hope  that  it  will  be  useful , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the  GNU 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  Lesser  General  Public  License  for  more  details . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  You  should  have  received  a  copy  of  the  GNU  Lesser  General  Public 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  License  along  with  this  library ;  if  not ,  write  to  the  Free  Software 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 *  Foundation ,  Inc . ,  51  Franklin  Street ,  Fifth  Floor ,  Boston ,  MA   02110 - 1301   USA 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 * 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				 */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    Holds  one  embedded  window ,  registers  as  DBus  entry 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    SPDX - FileCopyrightText :  2015  David  Edmundson  < davidedmundson @ kde . org > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    SPDX - FileCopyrightText :  2019  Konrad  Materka  < materka @ gmail . com > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    SPDX - License - Identifier :  LGPL - 2.1 - or - later 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				*/ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  "sniproxy.h" 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  < xcb/xcb.h >
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <algorithm> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <xcb/xcb_atom.h> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <xcb/xcb_event.h> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <xcb/xcb_image.h> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  "debug.h" 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  "xcbutils.h" 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QX11Info> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QScreen> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QGuiApplication> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QScreen> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QTimer> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <Q Debug >
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <Q X11Info >
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# include  <QBitmap> 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -48,13 +35,12 @@
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# define SNI_WATCHER_SERVICE_NAME "org.kde.StatusNotifierWatcher" 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# define SNI_WATCHER_PATH " / StatusNotifierWatcher" 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				static  uint16_t  s_embedSize  =  32 ;  //max size of window to embed. We no longer resize the embedded window as Chromium acts stupidly.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				static  uint16_t  s_embedSize  =  32 ;  // max size of window to embed. We no longer resize the embedded window as Chromium acts stupidly.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				static  unsigned  int  XEMBED_VERSION  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				int  SNIProxy : : s_serviceCount  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				xembed_message_send ( xcb_window_t  towin , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    long  message ,  long  d1 ,  long  d2 ,  long  d3 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  xembed_message_send ( xcb_window_t  towin ,  long  message ,  long  d1 ,  long  d2 ,  long  d3 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_client_message_event_t  ev ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -67,57 +53,63 @@ xembed_message_send(xcb_window_t towin,
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ev . data . data32 [ 3 ]  =  d2 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ev . data . data32 [ 4 ]  =  d3 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ev . type  =  Xcb : : atoms - > xembedAtom ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_send_event ( QX11Info : : connection ( ) ,  false ,  towin ,  XCB_EVENT_MASK_NO_EVENT ,  ( char  * )   & ev ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_send_event ( QX11Info : : connection ( ) ,  false ,  towin ,  XCB_EVENT_MASK_NO_EVENT ,  ( char  * ) & ev ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				SNIProxy : : SNIProxy ( xcb_window_t  wid ,  QObject *  parent ) : 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QObject ( parent ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //Work round a bug in our SNIWatcher with multiple SNIs per connection.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //there is an undocumented feature that you can register an SNI by path, however it doesn't detect an object on a service being removed, only the entire service closing
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //instead lets use one DBus connection per SNI
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_dbus ( QDBusConnection : : connectToBus ( QDBusConnection : : SessionBus ,  QStringLiteral ( " XembedSniProxy%1 " ) . arg ( s_serviceCount + + ) ) ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_windowId ( wid ) , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_injectMode ( Direct ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				SNIProxy : : SNIProxy ( xcb_window_t  wid ,  QObject  * parent ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    :  QObject ( parent ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // Work round a bug in our SNIWatcher with multiple SNIs per connection.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // there is an undocumented feature that you can register an SNI by path, however it doesn't detect an object on a service being removed, only the entire
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // service closing instead lets use one DBus connection per SNI
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_dbus ( QDBusConnection : : connectToBus ( QDBusConnection : : SessionBus ,  QStringLiteral ( " XembedSniProxy%1 " ) . arg ( s_serviceCount + + ) ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ,  m_windowId ( wid ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ,  sendingClickEvent ( false ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    ,  m_injectMode ( Direct ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //create new SNI
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   create new SNI
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    new  StatusNotifierItemAdaptor ( this ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_dbus . registerObject ( QStringLiteral ( " /StatusNotifierItem " ) ,  this ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  statusNotifierWatcher  =  new  org : : kde : : StatusNotifierWatcher ( QStringLiteral ( SNI_WATCHER_SERVICE_NAME ) ,  QStringLiteral ( SNI_WATCHER_PATH ) ,  QDBusConnection : : sessionBus ( ) ,  this ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  statusNotifierWatcher  = 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        new  org : : kde : : StatusNotifierWatcher ( QStringLiteral ( SNI_WATCHER_SERVICE_NAME ) ,  QStringLiteral ( SNI_WATCHER_PATH ) ,  QDBusConnection : : sessionBus ( ) ,  this ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  reply  =  statusNotifierWatcher - > RegisterStatusNotifierItem ( m_dbus . baseService ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    reply . waitForFinished ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( reply . isError ( ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q Warning( )  < <  " could not register SNI: "  < <  reply . error ( ) . message ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q C Warning( SNIPROXY )  < <  " could not register SNI: "  < <  reply . error ( ) . message ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  cookie  =  xcb_get_geometry ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_geometry_reply_t ,  QScopedPointerPodDeleter > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientGeom ( xcb_get_geometry_reply ( c ,  cookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //create a container window
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  screen  =  xcb_setup_roots_iterator  ( xcb_get_setup  ( c ) ) . data ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // create a container window
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  screen  =  xcb_setup_roots_iterator ( xcb_get_setup ( c ) ) . data ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_containerWid  =  xcb_generate_id ( c ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint32_t  values [ 2 ] ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  mask  =  XCB_CW_BACK_PIXEL  |  XCB_CW_OVERRIDE_REDIRECT ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    values [ 0 ]  =  screen - > black_pixel ;  //draw a solid background so the embedded icon doesn't get garbage in it
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    values [ 1 ]  =  true ;  //bypass wM
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_create_window  ( c ,                           /* connection    */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                    XCB_COPY_FROM_PARENT ,           /* depth         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     m_containerWid ,                /* window Id     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     screen - > root ,                  /* parent window */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     0 ,  0 ,                          /* x, y          */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     s_embedSize ,  s_embedSize ,      /* width, height */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     0 ,                             /* border_width  */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     XCB_WINDOW_CLASS_INPUT_OUTPUT , /* class         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     screen - > root_visual ,           /* visual        */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                     mask ,  values ) ;                 /* masks         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint32_t  values [ 3 ] ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint32_t  mask  =  XCB_CW_BACK_PIXEL  |  XCB_CW_OVERRIDE_REDIRECT  |  XCB_CW_EVENT_MASK ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    values [ 0 ]  =  screen - > black_pixel ;  // draw a solid background so the embedded icon doesn't get garbage in it
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    values [ 1 ]  =  true ;  // bypass wM
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    values [ 2 ]  =  XCB_EVENT_MASK_VISIBILITY_CHANGE  |  // receive visibility change, to handle KWin restart #357443
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                                   // Redirect and handle structure (size, position) requests from the embedded window.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        XCB_EVENT_MASK_STRUCTURE_NOTIFY  |  XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY  |  XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_create_window ( c ,  /* connection    */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      XCB_COPY_FROM_PARENT ,  /* depth         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      m_containerWid ,  /* window Id     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      screen - > root ,  /* parent window */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      0 , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      0 ,  /* x, y          */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      s_embedSize , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      s_embedSize ,  /* width, height */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      0 ,  /* border_width  */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      XCB_WINDOW_CLASS_INPUT_OUTPUT ,  /* class         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      screen - > root_visual ,  /* visual        */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      mask , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                      values ) ;  /* masks         */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    /*
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        We  need  the  window  to  exist  and  be  mapped  otherwise  the  child  won ' t  render  it ' s  contents 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        We  also  need  it  to  exist  in  the  right  place  to  get  the  clicks  working  as  GTK  will  check  sendEvent  locations  to  see  if  our  window  is  in  the  right  place .  So  even  though  our  contents  are  drawn  via  compositing  we  still  put  this  window  in  the  right  place 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        We  also  need  it  to  exist  in  the  right  place  to  get  the  clicks  working  as  GTK  will  check  sendEvent  locations  to  see  if  our  window  is  in  the  right  place . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				       So  even  though  our  contents  are  drawn  via  compositing  we  still  put  this  window  in  the  right  place 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        We  can ' t  composite  it  away  anything  parented  owned  by  the  root  window  ( apparently ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        Stack  Under  works  in  the  non  composited  case ,  but  it  doesn ' t  seem  to  work  in  kwin ' s  composited  case  ( probably  need  set  relevant  NETWM  hint ) 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -126,8 +118,7 @@ SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent):
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifndef VISUAL_DEBUG 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  stackBelowData [ ]  =  { XCB_STACK_MODE_BELOW } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  m_containerWid ,  XCB_CONFIG_WINDOW_STACK_MODE ,  stackBelowData ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    stackContainerWindow ( XCB_STACK_MODE_BELOW ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    NETWinInfo  wm ( c ,  m_containerWid ,  screen - > root ,  NET : : Properties ( ) ,  NET : : Properties2 ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    wm . setOpacity ( 0 ) ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -137,85 +128,51 @@ SNIProxy::SNIProxy(xcb_window_t wid, QObject* parent):
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_map_window ( c ,  m_containerWid ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_reparent_window ( c ,  wid , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        m_containerWid , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                        0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_reparent_window ( c ,  wid ,  m_containerWid ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    /*
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     *  Render  the  embedded  window  offscreen 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_composite_redirect_window ( c ,  wid ,  XCB_COMPOSITE_REDIRECT_MANUAL ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    /* we grab the window, but also make sure it's automatically reparented back
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				     *  to  the  root  window  if  we  should  die . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				      */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_change_save_set ( c ,  XCB_SET_MODE_INSERT ,  wid ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // tell client we're embedding it
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xembed_message_send ( wid ,  XEMBED_EMBEDDED_NOTIFY ,  m_containerWid ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   tell client we're embedding it
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xembed_message_send ( wid ,  XEMBED_EMBEDDED_NOTIFY ,  0 ,  m_containerWid ,  XEMBED_VERSION ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // move window we're embedding
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  windowMoveConfigVals [ 2 ]  =  {   0 ,  0   } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   move window we're embedding
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  windowMoveConfigVals [ 2 ]  =  { 0 ,  0 } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  wid , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             XCB_CONFIG_WINDOW_X  |  XCB_CONFIG_WINDOW_Y , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                             windowMoveConfigVals ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  wid ,  XCB_CONFIG_WINDOW_X  |  XCB_CONFIG_WINDOW_Y ,  windowMoveConfigVals ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QSize  clientWindowSize  =  calculateClientWindowSize ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QSize  clientWindowSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( clientGeom )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientWindowSize  =  QSize ( clientGeom - > width ,  clientGeom - > height ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //if the window is a clearly stupid size resize to be something sensible
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //this is needed as chormium and such when resized just fill the icon with transparent space and only draw in the middle
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //however spotify does need this as by default the window size is 900px wide.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //use an artbitrary heuristic to make sure icons are always sensible
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( clientWindowSize . isEmpty ( )  | |  clientWindowSize . width ( )  >  s_embedSize  | |  clientWindowSize . height ( )  >  s_embedSize  ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        qDebug ( )  < <  " Resizing window "  < <  wid  < <  Title ( )  < <  " from w*h "  < <  clientWindowSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_configure_notify_event_t  event ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        memset ( & event ,  0x00 ,  sizeof ( xcb_configure_notify_event_t ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event . response_type  =  XCB_CONFIGURE_NOTIFY ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event . event  =  wid ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event . window  =  wid ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event . width  =  s_embedSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event . height  =  s_embedSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_send_event ( c ,  false ,  wid ,  XCB_EVENT_MASK_STRUCTURE_NOTIFY ,  ( char  * )  & event ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        const  uint32_t  windowMoveConfigVals [ 2 ]  =  {  s_embedSize ,  s_embedSize  } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_configure_window ( c ,  wid , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                XCB_CONFIG_WINDOW_WIDTH  |  XCB_CONFIG_WINDOW_HEIGHT , 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				                                windowMoveConfigVals ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientWindowSize  =  QSize ( s_embedSize ,  s_embedSize ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //show the embedded window otherwise nothing happens
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // show the embedded window otherwise nothing happens
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_map_window ( c ,  wid ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_clear_area ( c ,  0 ,  wid ,  0 ,  0 ,  clientWindowSize . width ( ) ,  clientWindowSize . height ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_flush ( c ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // guess which input injection method to use
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // we can either send an X event to the client or XTest
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // some don't support direct X events (GTK3/4), and some don't support XTest because reasons
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // note also some clients might not have the XTest extension. We may as well assume it does and just fail to send later.
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // guess which input injection method to use
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // we can either send an X event to the client or XTest
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // some don't support direct X events (GTK3/4), and some don't support XTest because reasons
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // note also some clients might not have the XTest extension. We may as well assume it does and just fail to send later.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // we query if the client selected button presses in the event mask
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // if the client does supports that we send directly, otherwise we'll use xtest
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // we query if the client selected button presses in the event mask
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // if the client does supports that we send directly, otherwise we'll use xtest
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  waCookie  =  xcb_get_window_attributes ( c ,  wid ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_window_attributes_reply_t ,  QScopedPointerPodDeleter >  windowAttributes ( xcb_get_window_attributes_reply ( c ,  waCookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( windowAttributes  & &  !   ( windowAttributes - > all_event_masks  &  XCB_EVENT_MASK_BUTTON_PRESS ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( windowAttributes  & &  ! ( windowAttributes - > all_event_masks  &  XCB_EVENT_MASK_BUTTON_PRESS ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        m_injectMode  =  XTest ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // there's no damage event for the first paint, and sometimes it's not drawn immediately
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // not ideal, but it works better than nothing
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // test with xchat before changing
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // there's no damage event for the first paint, and sometimes it's not drawn immediately
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // not ideal, but it works better than nothing
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // test with xchat before changing
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QTimer : : singleShot ( 500 ,  this ,  & SNIProxy : : update ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -231,7 +188,7 @@ void SNIProxy::update()
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  QImage  image  =  getImageNonComposite ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( image . isNull ( ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q Debug( )  < <  " No xembed icon for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q C Debug( SNIPROXY )  < <  " No xembed icon for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -239,25 +196,73 @@ void SNIProxy::update()
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    int  h  =  image . height ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    m_pixmap  =  QPixmap : : fromImage ( image ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( w  !=  s_embedSize  | |  h  ! =   s_embedSize )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q Debug( )  < <  " Scaling pixmap of window "  < <  m_windowId  < <  Title ( )  < <  " from w*h "  < <  w  < <  h ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( w  > s_embedSize  | |  h  >   s_embedSize )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q C Debug( SNIPROXY )  < <  " Scaling pixmap of window "  < <  m_windowId  < <  Title ( )  < <  " from w*h "  < <  w  < <  h ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        m_pixmap  =  m_pixmap . scaled ( s_embedSize ,  s_embedSize ,  Qt : : KeepAspectRatio ,  Qt : : SmoothTransformation ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    emit  NewIcon ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    emit  NewToolTip ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  sni_cleanup_xcb_image ( void  * data )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_image_destroy ( static_cast < xcb_image_t * > ( data ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : resizeWindow ( const  uint16_t  width ,  const  uint16_t  height )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  connection  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint16_t  widthNormalized  =  std : : min ( width ,  s_embedSize ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint16_t  heighNormalized  =  std : : min ( height ,  s_embedSize ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  windowSizeConfigVals [ 2 ]  =  { widthNormalized ,  heighNormalized } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( connection ,  m_windowId ,  XCB_CONFIG_WINDOW_WIDTH  |  XCB_CONFIG_WINDOW_HEIGHT ,  windowSizeConfigVals ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_flush ( connection ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				bool  SNIProxy : : isTransparentImage ( const  QImage &  image )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : hideContainerWindow ( xcb_window_t  windowId )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( m_containerWid  = =  windowId  & &  ! sendingClickEvent )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        qDebug ( )  < <  " Container window visible, stack below " ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        stackContainerWindow ( XCB_STACK_MODE_BELOW ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QSize  SNIProxy : : calculateClientWindowSize ( )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  cookie  =  xcb_get_geometry ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_geometry_reply_t ,  QScopedPointerPodDeleter >  clientGeom ( xcb_get_geometry_reply ( c ,  cookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QSize  clientWindowSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( clientGeom )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientWindowSize  =  QSize ( clientGeom - > width ,  clientGeom - > height ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // if the window is a clearly stupid size resize to be something sensible
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // this is needed as chromium and such when resized just fill the icon with transparent space and only draw in the middle
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // however KeePass2 does need this as by default the window size is 273px wide and is not transparent
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // use an arbitrary heuristic to make sure icons are always sensible
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( clientWindowSize . isEmpty ( )  | |  clientWindowSize . width ( )  >  s_embedSize  | |  clientWindowSize . height ( )  >  s_embedSize )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        qCDebug ( SNIPROXY )  < <  " Resizing window "  < <  m_windowId  < <  Title ( )  < <  " from w*h "  < <  clientWindowSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        resizeWindow ( s_embedSize ,  s_embedSize ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientWindowSize  =  QSize ( s_embedSize ,  s_embedSize ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    return  clientWindowSize ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  sni_cleanup_xcb_image ( void  * data ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_image_destroy ( static_cast < xcb_image_t  * > ( data ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				bool  SNIProxy : : isTransparentImage ( const  QImage  & image )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    int  w  =  image . width ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    int  h  =  image . height ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // check for the center and sub-center pixels first and avoid full image scan
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( !  ( qAlpha ( image . pixel ( w  > >  1 ,  h  > >  1 ) )  +  qAlpha ( image . pixel ( w  > >  2 ,  h  > >  2 ) )  = =  0 ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( ! ( qAlpha ( image . pixel ( w  > >  1 ,  h  > >  1 ) )  +  qAlpha ( image . pixel ( w  > >  2 ,  h  > >  2 ) )  = =  0 ) ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  false ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // skip scan altogether if sub-center pixel found to be opaque
 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -277,22 +282,17 @@ bool SNIProxy::isTransparentImage(const QImage& image) const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QImage  SNIProxy : : getImageNonComposite ( )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  cookie  =  xcb_get_geometry ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_geometry_reply_t ,  QScopedPointerPodDeleter > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        geom ( xcb_get_geometry_reply ( c ,  cookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( ! geom )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  QImage ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QSize  clientWindowSize  =  calculateClientWindowSize ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_image_t  * image  =  xcb_image_get ( c ,  m_windowId ,  0 ,  0 ,  geom- > width ,  geom - > height  ,  0xFFFFFFFF ,  XCB_IMAGE_FORMAT_Z_PIXMAP ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_image_t  * image  =  xcb_image_get ( c ,  m_windowId ,  0 ,  0 ,  clientWindowSize . width ( ) ,  clientWindowSize . height ( ) ,  0xFFFFFFFF ,  XCB_IMAGE_FORMAT_Z_PIXMAP ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // Don't hook up cleanup yet, we may use a different QImage after all
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QImage  naiveConversion ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( image )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        naiveConversion  =  QImage ( image - > data ,  image - > width ,  image - > height ,  QImage : : Format_ARGB32 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q Debug( )  < <  " Skip NULL image returned from xcb_image_get() for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        q C Debug( SNIPROXY )  < <  " Skip NULL image returned from xcb_image_get() for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  QImage ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -304,7 +304,7 @@ QImage SNIProxy::getImageNonComposite() const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        // become transparent for a one or few frames. Reproducible at least
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        // with WINE applications.
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        if  ( isTransparentImage ( elaborateConversion ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            q Debug( )  < <  " Skip transparent xembed icon for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            q C Debug( SNIPROXY )  < <  " Skip transparent xembed icon for "  < <  m_windowId  < <  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            return  QImage ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        }  else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            return  elaborateConversion ; 
 
			
		 
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
			
			 
			 
			
				@ -334,11 +334,12 @@ QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        for  ( uint  i  =  0 ;  i  <  ( xcbImage - > size  /  4 ) ;  i + + )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            int  r  =  ( pixels [ i ]  > >  22 )  &  0xff ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            int  g  =  ( pixels [ i ]  > >  12 )  &  0xff ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            int  b  =  ( pixels [ i ]  > >    2 )  &  0xff ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            int  b  =  ( pixels [ i ]  > >  2 )  &  0xff ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            pixels [ i ]  =  qRgba ( r ,  g ,  b ,  0xff ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        // fall through, Qt format is still Format_ARGB32_Premultiplied
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        Q_FALLTHROUGH ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    case  32 : 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        format  =  QImage : : Format_ARGB32_Premultiplied ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -353,8 +354,7 @@ QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  QImage ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( format  = =  QImage : : Format_RGB32  & &  xcbImage - > bpp  = =  32 ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( format  = =  QImage : : Format_RGB32  & &  xcbImage - > bpp  = =  32 )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        QImage  m  =  image . createHeuristicMask ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        QBitmap  mask ( QPixmap : : fromImage ( m ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        QPixmap  p  =  QPixmap : : fromImage ( image ) ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -372,6 +372,56 @@ QImage SNIProxy::convertFromNative(xcb_image_t *xcbImage) const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    return  image ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				/*
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  Wine  is  using  XWindow  Shape  Extension  for  transparent  tray  icons . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				  We  need  to  find  first  clickable  point  starting  from  top - left . 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				*/ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QPoint  SNIProxy : : calculateClickPoint ( )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QPoint  clickPoint  =  QPoint ( 0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // request extent to check if shape has been set
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_shape_query_extents_cookie_t  extentsCookie  =  xcb_shape_query_extents ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // at the same time make the request for rectangles (even if this request isn't needed)
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_shape_get_rectangles_cookie_t  rectaglesCookie  =  xcb_shape_get_rectangles ( c ,  m_windowId ,  XCB_SHAPE_SK_BOUNDING ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_shape_query_extents_reply_t ,  QScopedPointerPodDeleter >  extentsReply ( xcb_shape_query_extents_reply ( c ,  extentsCookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_shape_get_rectangles_reply_t ,  QScopedPointerPodDeleter >  rectanglesReply ( xcb_shape_get_rectangles_reply ( c ,  rectaglesCookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( ! extentsReply  | |  ! rectanglesReply  | |  ! extentsReply - > bounding_shaped )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  clickPoint ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_rectangle_t  * rectangles  =  xcb_shape_get_rectangles_rectangles ( rectanglesReply . get ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( ! rectangles )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  clickPoint ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  QImage  image  =  getImageNonComposite ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    double  minLength  =  sqrt ( pow ( image . height ( ) ,  2 )  +  pow ( image . width ( ) ,  2 ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  int  nRectangles  =  xcb_shape_get_rectangles_rectangles_length ( rectanglesReply . get ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    for  ( int  i  =  0 ;  i  <  nRectangles ;  + + i )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        double  length  =  sqrt ( pow ( rectangles [ i ] . x ,  2 )  +  pow ( rectangles [ i ] . y ,  2 ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        if  ( length  <  minLength )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            minLength  =  length ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				            clickPoint  =  QPoint ( rectangles [ i ] . x ,  rectangles [ i ] . y ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    qCDebug ( SNIPROXY )  < <  " Click point: "  < <  clickPoint ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    return  clickPoint ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : stackContainerWindow ( const  uint32_t  stackMode )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  stackData [ ]  =  { stackMode } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  m_containerWid ,  XCB_CONFIG_WINDOW_STACK_MODE ,  stackData ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				//____________properties__________
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QString  SNIProxy : : Category ( )  const 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -382,7 +432,7 @@ QString SNIProxy::Category() const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QString  SNIProxy : : Id ( )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  auto  title  =  Title ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // we always need /some/ ID so if no window title exists, just use the winId.
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   we always need /some/ ID so if no window title exists, just use the winId.
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( title . isEmpty ( ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return  QString : : number ( m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -407,7 +457,7 @@ QString SNIProxy::Status() const
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				QString  SNIProxy : : Title ( )  const 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    KWindowInfo  window   ( m_windowId ,  NET : : WMName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    KWindowInfo  window ( m_windowId ,  NET : : WMName ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    return  window . name ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -433,69 +483,68 @@ void SNIProxy::ContextMenu(int x, int y)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    sendClick ( XCB_BUTTON_INDEX_3 ,  x ,  y ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : Scroll ( int  delta ,  const  QString &   orientation ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : Scroll ( int  delta ,  const  QString   & orientation ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( orientation  = =  QLatin1String ( " vertical " ) )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendClick ( delta  >  0  ?  XCB_BUTTON_INDEX_4 :  XCB_BUTTON_INDEX_5 ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendClick ( delta  >  0  ?  XCB_BUTTON_INDEX_4   :  XCB_BUTTON_INDEX_5 ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendClick ( delta  >  0  ?  6 :  7 ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendClick ( delta  >  0  ?  6   :  7 ,  0 ,  0 ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				} 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				void  SNIProxy : : sendClick ( uint8_t  mouseButton ,  int  x ,  int  y ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				{ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // it's best not to look at this code
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // GTK doesn't like send_events and double checks the mouse position matches where the window is and is top level
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // in order to solve this we move the embed container over to where the mouse is then replay the event using send_event
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // if patching, test with xchat + xchat context menus
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   it's best not to look at this code
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   GTK doesn't like send_events and double checks the mouse position matches where the window is and is top level
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   in order to solve this we move the embed container over to where the mouse is then replay the event using send_event
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   if patching, test with xchat + xchat context menus
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // note x,y are not actually where the mouse is, but the plasmoid
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // ideally we should make this match the plasmoid hit area
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   note x,y are not actually where the mouse is, but the plasmoid
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   ideally we should make this match the plasmoid hit area
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    qDebug ( )  < <  " Received click "  < <  mouseButton  < <  " with passed x*y "  < <  x  < <  y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    qCDebug ( SNIPROXY )  < <  " Received click "  < <  mouseButton  < <  " with passed x*y "  < <  x  < <  y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    sendingClickEvent  =  true ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  c  =  QX11Info : : connection ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  cookieSize  =  xcb_get_geometry ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_geometry_reply_t ,  QScopedPointerPodDeleter > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        clientGeom ( xcb_get_geometry_reply ( c ,  cookieSize ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_get_geometry_reply_t ,  QScopedPointerPodDeleter >  clientGeom ( xcb_get_geometry_reply ( c ,  cookieSize ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( ! clientGeom )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        return ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    auto  cookie  =  xcb_query_pointer ( c ,  m_windowId ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_query_pointer_reply_t ,  QScopedPointerPodDeleter > 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        pointer ( xcb_query_pointer_reply ( c ,  cookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    /*qDebug() << "samescreen" << pointer->same_screen << endl
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					< <  " root x*y "  < <  pointer - > root_x  < <  pointer - > root_y  < <  endl 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					< <  " win x*y "  < <  pointer - > win_x  < <  pointer - > win_y ; */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    QScopedPointer < xcb_query_pointer_reply_t ,  QScopedPointerPodDeleter >  pointer ( xcb_query_pointer_reply ( c ,  cookie ,  nullptr ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    /*qCDebug(SNIPROXY) << "samescreen" << pointer->same_screen << endl
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    < <  " root x*y "  < <  pointer - > root_x  < <  pointer - > root_y  < <  endl 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    < <  " win x*y "  < <  pointer - > win_x  < <  pointer - > win_y ; */ 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // move our window so the mouse is within its geometry
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   move our window so the mouse is within its geometry
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    uint32_t  configVals [ 2 ]  =  { 0 ,  0 } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  QPoint  clickPoint  =  calculateClickPoint ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( mouseButton  > =  XCB_BUTTON_INDEX_4 )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					//  scroll event, take pointer position
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 configVals [ 0 ]  =  pointer - > root_x ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 configVals [ 1 ]  =  pointer - > root_y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        //   scroll event, take pointer position
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         configVals [ 0 ]  =  pointer - > root_x ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         configVals [ 1 ]  =  pointer - > root_y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 if  ( pointer - > root_x  >  x  +  clientGeom - > width ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					     configVals [ 0 ]  =  pointer - > root_x  -  clientGeom - > width  +  1 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					     configVals [ 0 ]  =  static_cast < uint32_t > ( x ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 if  ( pointer - > root_y  >  y  +  clientGeom - > height ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					     configVals [ 1 ]  =  pointer - > root_y  -  clientGeom - > height  +  1 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					 else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
					     configVals [ 1 ]  =  static_cast < uint32_t > ( y ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if  ( pointer - > root_x  >  x  +  clientGeom - > width ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             configVals [ 0 ]  =  pointer - > root_x  -  clientGeom - > width  +  1 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             configVals [ 0 ]  =  static_cast < uint32_t > ( x  -  clickPoint . x ( )  ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         if  ( pointer - > root_y  >  y  +  clientGeom - > height ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             configVals [ 1 ]  =  pointer - > root_y  -  clientGeom - > height  +  1 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				         else 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				             configVals [ 1 ]  =  static_cast < uint32_t > ( y  -  clickPoint . y ( )  ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  m_containerWid ,  XCB_CONFIG_WINDOW_X  |  XCB_CONFIG_WINDOW_Y ,  configVals ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //pull window up
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  stackAboveData [ ]  =  { XCB_STACK_MODE_ABOVE } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  m_containerWid ,  XCB_CONFIG_WINDOW_STACK_MODE ,  stackAboveData ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // pull window up
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    stackContainerWindow ( XCB_STACK_MODE_ABOVE ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // mouse down
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //   mouse down
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( m_injectMode  = =  Direct )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_button_press_event_t *   event  =  new  xcb_button_press_event_t ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_button_press_event_t   * event  =  new  xcb_button_press_event_t ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        memset ( event ,  0x00 ,  sizeof ( xcb_button_press_event_t ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > response_type  =  XCB_BUTTON_PRESS ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event  =  m_windowId ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -504,22 +553,21 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root  =  QX11Info : : appRootWindow ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root_x  =  x ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root_y  =  y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_x  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_y  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_x  =  static_cast < int16_t > ( clickPoint . x ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_y  =  static_cast < int16_t > ( clickPoint . y ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > child  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > state  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > detail  =  mouseButton ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_send_event ( c ,  false ,  m_windowId ,  XCB_EVENT_MASK_BUTTON_PRESS ,  ( char  * )   event ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_send_event ( c ,  false ,  m_windowId ,  XCB_EVENT_MASK_BUTTON_PRESS ,  ( char  * ) event ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        delete  event ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendXTestPressed ( QX11Info : : display ( ) ,  mouseButton ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    //mouse up
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( m_injectMode  = =  Direct ) 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_button_release_event_t *  event  =  new  xcb_button_release_event_t ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    // mouse up
 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    if  ( m_injectMode  = =  Direct )  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_button_release_event_t  * event  =  new  xcb_button_release_event_t ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        memset ( event ,  0x00 ,  sizeof ( xcb_button_release_event_t ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > response_type  =  XCB_BUTTON_RELEASE ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event  =  m_windowId ; 
 
			
		 
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
			
			 
			 
			
				@ -528,20 +576,21 @@ void SNIProxy::sendClick(uint8_t mouseButton, int x, int y)
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root  =  QX11Info : : appRootWindow ( ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root_x  =  x ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > root_y  =  y ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_x  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_y  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_x  =  static_cast < int16_t > ( clickPoint . x ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > event_y  =  static_cast < int16_t > ( clickPoint . y ( ) ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > child  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > state  =  0 ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        event - > detail  =  mouseButton ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_send_event ( c ,  false ,  m_windowId ,  XCB_EVENT_MASK_BUTTON_RELEASE ,  ( char  * )   event ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        xcb_send_event ( c ,  false ,  m_windowId ,  XCB_EVENT_MASK_BUTTON_RELEASE ,  ( char  * ) event ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        delete  event ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    }  else  { 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				        sendXTestReleased ( QX11Info : : display ( ) ,  mouseButton ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    } 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# ifndef VISUAL_DEBUG 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    const  uint32_t  stackBelowData [ ]  =  { XCB_STACK_MODE_BELOW } ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    xcb_configure_window ( c ,  m_containerWid ,  XCB_CONFIG_WINDOW_STACK_MODE ,  stackBelowData ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    stackContainerWindow ( XCB_STACK_MODE_BELOW ) ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				# endif 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				    sendingClickEvent  =  false ; 
 
			
		 
		
	
		
			
				 
				 
			
			 
			 
			
				}