@ -9,6 +9,7 @@
# include "ext-image-capture-source-v1.prot.h"
# include "ext-image-copy-capture-v1.prot.h"
# include "ext-foreign-toplevel-list-v1.prot.h"
# include "rif.h"
@ -34,6 +35,8 @@ struct wl_shm* wl_shm = NULL;
struct wl_buffer * frame_buffer = NULL ;
struct ext_output_image_capture_source_manager_v1 * output_source_manager = NULL ;
struct ext_image_copy_capture_manager_v1 * capture_manager = NULL ;
struct ext_foreign_toplevel_list_v1 * toplevel_list = NULL ;
struct ext_foreign_toplevel_image_capture_source_manager_v1 * toplevel_source_manager = NULL ;
void * shm_data = NULL ;
@ -41,6 +44,7 @@ struct image_data img_data;
uint8_t is_frame_ready = 0 ;
uint8_t is_capture_ready = 0 ;
uint8_t full_screenshot = 0 ;
uint32_t buf_size ;
@ -62,6 +66,12 @@ void handle_global(
if ( strcmp ( interface , ext_image_copy_capture_manager_v1_interface . name ) = = 0 ) {
capture_manager = wl_registry_bind ( registry , name , & ext_image_copy_capture_manager_v1_interface , version ) ;
}
if ( strcmp ( interface , ext_foreign_toplevel_list_v1_interface . name ) = = 0 ) {
toplevel_list = wl_registry_bind ( registry , name , & ext_foreign_toplevel_list_v1_interface , version ) ;
}
if ( strcmp ( interface , ext_foreign_toplevel_image_capture_source_manager_v1_interface . name ) = = 0 ) {
toplevel_source_manager = wl_registry_bind ( registry , name , & ext_foreign_toplevel_image_capture_source_manager_v1_interface , version ) ;
}
}
void handle_global_remove (
@ -76,8 +86,8 @@ const struct wl_registry_listener reg_callbacks = {
. global_remove = handle_global_remove ,
} ;
void buffer_size ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
void buffer_size ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
uint32_t width ,
uint32_t height ) {
printf ( " x: %d, y: %d \n " , width , height ) ;
@ -85,36 +95,36 @@ void buffer_size(void *data,
img_data . height = height ;
}
void shm_format ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
void shm_format ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
uint32_t format ) {
img_data . shm_format = format ;
ASSERT ( format = = WL_SHM_FORMAT_XBGR8888 | | format = = WL_SHM_FORMAT_ABGR8888 , " Unsupported buffer format. " ) ;
}
void dmabuf_device ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
struct wl_array * device ) {
void dmabuf_device ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
struct wl_array * device ) {
}
void dmabuf_format ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
void dmabuf_format ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ,
uint32_t format ,
struct wl_array * modifiers ) {
struct wl_array * modifiers ) {
}
void done( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ) {
void capture_ done( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ) {
const int shm_fd = memfd_create ( " wl_shm data " , 0 ) ;
ASSERT ( shm_fd ! = - 1 , " Failed to create memfd. " ) ;
// Format is hardcoded to chan width 4
const uint32_t chan_width = 4 ;
const uint32_t stride = img_data . width * chan_width ;
buf_size = img_data . height * stride ;
const uint32_t stride = img_data . width * chan_width ;
buf_size = img_data . height * stride ;
ASSERT ( ftruncate ( shm_fd , buf_size ) ! = - 1 , " Failed to ftruncate the memfd. " ) ;
@ -131,8 +141,8 @@ void done(void *data,
}
void stopped ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ) {
void stopped ( void * data ,
struct ext_image_copy_capture_session_v1 * ext_image_copy_capture_session_v1 ) {
}
@ -141,37 +151,37 @@ const struct ext_image_copy_capture_session_v1_listener capture_listener = {
. shm_format = shm_format ,
. dmabuf_device = dmabuf_device ,
. dmabuf_format = dmabuf_format ,
. done = done,
. done = capture_ done,
. stopped = stopped
} ;
void transform ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
void transform ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
uint32_t transform ) {
}
void damage ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
void damage ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
int32_t x ,
int32_t y ,
int32_t width ,
int32_t height ) {
}
void presentation_time ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
void presentation_time ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
uint32_t tv_sec_hi ,
uint32_t tv_sec_lo ,
uint32_t tv_nsec ) {
}
void ready ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ) {
void ready ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ) {
is_capture_ready = 1 ;
}
void failed ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
void failed ( void * data ,
struct ext_image_copy_capture_frame_v1 * ext_image_copy_capture_frame_v1 ,
uint32_t reason ) {
switch ( reason ) {
case 0 :
@ -194,8 +204,90 @@ const struct ext_image_copy_capture_frame_v1_listener frame_listener = {
. failed = failed
} ;
struct handle_data {
struct ext_foreign_toplevel_handle_v1 * handle ;
const char * title ;
const char * app_id ;
const char * identifier ;
} ;
struct handle_data * * * handles ;
size_t handles_len = 0 ;
void closed ( void * data ,
struct ext_foreign_toplevel_handle_v1 * ext_foreign_toplevel_handle_v1 ) {
// TODO handle properly
}
void title ( void * data ,
struct ext_foreign_toplevel_handle_v1 * ext_foreign_toplevel_handle_v1 ,
const char * title ) {
struct handle_data * handle_data = ( struct handle_data * ) data ;
size_t size = strlen ( title ) + 1 ;
char * title_data = malloc ( size ) ;
memcpy ( title_data , title , size ) ;
handle_data - > title = title_data ;
}
void app_id ( void * data ,
struct ext_foreign_toplevel_handle_v1 * ext_foreign_toplevel_handle_v1 ,
const char * app_id ) {
struct handle_data * handle_data = ( struct handle_data * ) data ;
size_t size = strlen ( app_id ) + 1 ;
char * app_id_data = malloc ( size ) ;
memcpy ( app_id_data , app_id , size ) ;
handle_data - > app_id = app_id_data ;
}
void identifier ( void * data ,
struct ext_foreign_toplevel_handle_v1 * ext_foreign_toplevel_handle_v1 ,
const char * identifier ) {
struct handle_data * handle_data = ( struct handle_data * ) data ;
size_t size = strlen ( identifier ) + 1 ;
char * identifier_data = malloc ( size ) ;
memcpy ( identifier_data , identifier , size ) ;
handle_data - > identifier = identifier_data ;
}
void toplevel_done ( void * data ,
struct ext_foreign_toplevel_handle_v1 * ext_foreign_toplevel_handle_v1 ) {
struct handle_data * handle_data = ( struct handle_data * ) data ;
}
struct ext_foreign_toplevel_handle_v1_listener handle_listener = {
. closed = closed ,
. done = toplevel_done ,
. title = title ,
. app_id = app_id ,
. identifier = identifier ,
} ;
void toplevel ( void * data ,
struct ext_foreign_toplevel_list_v1 * ext_foreign_toplevel_list_v1 ,
struct ext_foreign_toplevel_handle_v1 * toplevel ) {
handles_len + + ;
* handles = realloc ( * handles , handles_len * sizeof ( void * ) ) ;
struct handle_data * handle_data = malloc ( sizeof ( struct handle_data ) ) ;
int main ( ) {
handle_data - > handle = toplevel ;
handle_data - > title = NULL ;
handle_data - > app_id = NULL ;
handle_data - > identifier = NULL ;
( * handles ) [ handles_len - 1 ] = handle_data ;
ext_foreign_toplevel_handle_v1_add_listener ( toplevel , & handle_listener , handle_data ) ;
}
void finished ( void * data ,
struct ext_foreign_toplevel_list_v1 * ext_foreign_toplevel_list_v1 ) {
// TODO handle exploding properly
}
const struct ext_foreign_toplevel_list_v1_listener toplevel_listener = {
. toplevel = toplevel ,
. finished = finished
} ;
int main ( int argc , char * argv [ ] ) {
struct wl_display * dpy = wl_display_connect ( NULL ) ;
ASSERT ( dpy ! = NULL , " Unable to connect to Wayland " ) ;
@ -208,11 +300,59 @@ int main() {
ASSERT ( stream_output ! = NULL , " No outputs found! " ) ;
ASSERT ( output_source_manager ! = NULL , " ext-image-capture-source-v1.ext_output_image_capture_source_manager_v1 not supported. " ) ;
struct handle_data * toplevel_handle = NULL ;
if ( argc = = 2 ) {
ASSERT ( toplevel_list ! = NULL , " ext-foreign-toplevel-list-v1.ext_foreign_toplevel_list_v1 not supported. " ) ;
handles = malloc ( sizeof ( void * ) ) ;
* handles = malloc ( sizeof ( void * ) ) ;
handles_len = 0 ;
ext_foreign_toplevel_list_v1_add_listener ( toplevel_list , & toplevel_listener , NULL ) ;
if ( strcmp ( argv [ 1 ] , " ? " ) = = 0 ) {
wl_display_roundtrip ( dpy ) ;
for ( int i = 0 ; i < handles_len ; i + + ) {
struct handle_data * handle_data = ( * handles ) [ i ] ;
printf ( " title: %s, app_id: %s, identifier: %s \n " , handle_data - > title , handle_data - > app_id , handle_data - > identifier ) ;
}
return 0 ;
} else {
wl_display_roundtrip ( dpy ) ;
for ( int i = 0 ; i < handles_len ; i + + ) {
if ( strcmp ( ( * handles ) [ i ] - > identifier , argv [ 1 ] ) = = 0 ) {
toplevel_handle = ( * handles ) [ i ] ;
printf ( " Found handle: " ) ;
printf ( " title: %s, app_id: %s, identifier: %s \n " , toplevel_handle - > title , toplevel_handle - > app_id , toplevel_handle - > identifier ) ;
}
}
}
} else if ( argc = = 1 ) {
full_screenshot = 1 ;
wl_display_roundtrip ( dpy ) ;
} else {
ASSERT ( argc > = 1 , " Invalid exec! " ) ;
printf ( " Usage: %s ?|<identifier> \n " ) ;
exit ( - 1 ) ;
}
ASSERT ( capture_manager ! = NULL , " ext-image-copy-capture-v1.ext_image_copy_capture_manager_v1 not supported. " ) ;
struct ext_image_capture_source_v1 * capture_source =
ext_output_image_capture_source_manager_v1_create_source ( output_source_manager , stream_output ) ;
ASSERT ( capture_source ! = NULL , " Failed creating a source for the default output! " )
struct ext_image_capture_source_v1 * capture_source ;
if ( full_screenshot ) {
ASSERT ( output_source_manager ! = NULL , " ext-image-capture-source-v1.ext_output_image_capture_source_manager_v1 not supported. " ) ;
capture_source =
ext_output_image_capture_source_manager_v1_create_source ( output_source_manager , stream_output ) ;
ASSERT ( capture_source ! = NULL , " Failed creating a source for the default output! " )
} else {
ASSERT ( toplevel_handle ! = NULL , " Invalid toplevel handle! " ) ;
ASSERT ( toplevel_source_manager ! = NULL , " ext-image-capture-source-v1.ext_foreign_toplevel_image_capture_source_manager_v1 not supported. " ) ;
capture_source =
ext_foreign_toplevel_image_capture_source_manager_v1_create_source ( toplevel_source_manager , toplevel_handle - > handle ) ;
ASSERT ( capture_source ! = NULL , " Failed creating a source for the toplevel! " )
}
struct ext_image_copy_capture_session_v1 * capture_session =
ext_image_copy_capture_manager_v1_create_session ( capture_manager , capture_source , EXT_IMAGE_COPY_CAPTURE_MANAGER_V1_OPTIONS_PAINT_CURSORS ) ;