@ -86,6 +86,7 @@ struct tinywl_toplevel {
struct wlr_scene_tree * scene_tree ;
struct wlr_scene_tree * scene_tree ;
struct wl_listener map ;
struct wl_listener map ;
struct wl_listener unmap ;
struct wl_listener unmap ;
struct wl_listener commit ;
struct wl_listener destroy ;
struct wl_listener destroy ;
struct wl_listener request_move ;
struct wl_listener request_move ;
struct wl_listener request_resize ;
struct wl_listener request_resize ;
@ -93,6 +94,12 @@ struct tinywl_toplevel {
struct wl_listener request_fullscreen ;
struct wl_listener request_fullscreen ;
} ;
} ;
struct tinywl_popup {
struct wlr_xdg_popup * xdg_popup ;
struct wl_listener commit ;
struct wl_listener destroy ;
} ;
struct tinywl_keyboard {
struct tinywl_keyboard {
struct wl_list link ;
struct wl_list link ;
struct tinywl_server * server ;
struct tinywl_server * server ;
@ -672,12 +679,26 @@ static void xdg_toplevel_unmap(struct wl_listener *listener, void *data) {
wl_list_remove ( & toplevel - > link ) ;
wl_list_remove ( & toplevel - > link ) ;
}
}
static void xdg_toplevel_commit ( struct wl_listener * listener , void * data ) {
/* Called when a new surface state is committed. */
struct tinywl_toplevel * toplevel = wl_container_of ( listener , toplevel , commit ) ;
if ( toplevel - > xdg_toplevel - > base - > initial_commit ) {
/* When an xdg_surface performs an initial commit, the compositor must
* reply with a configure so the client can map the surface . tinywl
* configures the xdg_toplevel with 0 , 0 size to let the client pick the
* dimensions itself . */
wlr_xdg_toplevel_set_size ( toplevel - > xdg_toplevel , 0 , 0 ) ;
}
}
static void xdg_toplevel_destroy ( struct wl_listener * listener , void * data ) {
static void xdg_toplevel_destroy ( struct wl_listener * listener , void * data ) {
/* Called when the xdg_toplevel is destroyed. */
/* Called when the xdg_toplevel is destroyed. */
struct tinywl_toplevel * toplevel = wl_container_of ( listener , toplevel , destroy ) ;
struct tinywl_toplevel * toplevel = wl_container_of ( listener , toplevel , destroy ) ;
wl_list_remove ( & toplevel - > map . link ) ;
wl_list_remove ( & toplevel - > map . link ) ;
wl_list_remove ( & toplevel - > unmap . link ) ;
wl_list_remove ( & toplevel - > unmap . link ) ;
wl_list_remove ( & toplevel - > commit . link ) ;
wl_list_remove ( & toplevel - > destroy . link ) ;
wl_list_remove ( & toplevel - > destroy . link ) ;
wl_list_remove ( & toplevel - > request_move . link ) ;
wl_list_remove ( & toplevel - > request_move . link ) ;
wl_list_remove ( & toplevel - > request_resize . link ) ;
wl_list_remove ( & toplevel - > request_resize . link ) ;
@ -793,6 +814,8 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
wl_signal_add ( & xdg_toplevel - > base - > surface - > events . map , & toplevel - > map ) ;
wl_signal_add ( & xdg_toplevel - > base - > surface - > events . map , & toplevel - > map ) ;
toplevel - > unmap . notify = xdg_toplevel_unmap ;
toplevel - > unmap . notify = xdg_toplevel_unmap ;
wl_signal_add ( & xdg_toplevel - > base - > surface - > events . unmap , & toplevel - > unmap ) ;
wl_signal_add ( & xdg_toplevel - > base - > surface - > events . unmap , & toplevel - > unmap ) ;
toplevel - > commit . notify = xdg_toplevel_commit ;
wl_signal_add ( & xdg_toplevel - > base - > surface - > events . commit , & toplevel - > commit ) ;
toplevel - > destroy . notify = xdg_toplevel_destroy ;
toplevel - > destroy . notify = xdg_toplevel_destroy ;
wl_signal_add ( & xdg_toplevel - > events . destroy , & toplevel - > destroy ) ;
wl_signal_add ( & xdg_toplevel - > events . destroy , & toplevel - > destroy ) ;
@ -808,10 +831,37 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) {
wl_signal_add ( & xdg_toplevel - > events . request_fullscreen , & toplevel - > request_fullscreen ) ;
wl_signal_add ( & xdg_toplevel - > events . request_fullscreen , & toplevel - > request_fullscreen ) ;
}
}
static void xdg_popup_commit ( struct wl_listener * listener , void * data ) {
/* Called when a new surface state is committed. */
struct tinywl_popup * popup = wl_container_of ( listener , popup , commit ) ;
if ( popup - > xdg_popup - > base - > initial_commit ) {
/* When an xdg_surface performs an initial commit, the compositor must
* reply with a configure so the client can map the surface .
* tinywl sends an empty configure . A more sophisticated compositor
* might change an xdg_popup ' s geometry to ensure it ' s not positioned
* off - screen , for example . */
wlr_xdg_surface_schedule_configure ( popup - > xdg_popup - > base ) ;
}
}
static void xdg_popup_destroy ( struct wl_listener * listener , void * data ) {
/* Called when the xdg_popup is destroyed. */
struct tinywl_popup * popup = wl_container_of ( listener , popup , destroy ) ;
wl_list_remove ( & popup - > commit . link ) ;
wl_list_remove ( & popup - > destroy . link ) ;
free ( popup ) ;
}
static void server_new_xdg_popup ( struct wl_listener * listener , void * data ) {
static void server_new_xdg_popup ( struct wl_listener * listener , void * data ) {
/* This event is raised when a client creates a new popup. */
/* This event is raised when a client creates a new popup. */
struct wlr_xdg_popup * xdg_popup = data ;
struct wlr_xdg_popup * xdg_popup = data ;
struct tinywl_popup * popup = calloc ( 1 , sizeof ( * popup ) ) ;
popup - > xdg_popup = xdg_popup ;
/* We must add xdg popups to the scene graph so they get rendered. The
/* We must add xdg popups to the scene graph so they get rendered. The
* wlroots scene graph provides a helper for this , but to use it we must
* wlroots scene graph provides a helper for this , but to use it we must
* provide the proper parent scene node of the xdg popup . To enable this ,
* provide the proper parent scene node of the xdg popup . To enable this ,
@ -821,6 +871,12 @@ static void server_new_xdg_popup(struct wl_listener *listener, void *data) {
assert ( parent ! = NULL ) ;
assert ( parent ! = NULL ) ;
struct wlr_scene_tree * parent_tree = parent - > data ;
struct wlr_scene_tree * parent_tree = parent - > data ;
xdg_popup - > base - > data = wlr_scene_xdg_surface_create ( parent_tree , xdg_popup - > base ) ;
xdg_popup - > base - > data = wlr_scene_xdg_surface_create ( parent_tree , xdg_popup - > base ) ;
popup - > commit . notify = xdg_popup_commit ;
wl_signal_add ( & xdg_popup - > base - > surface - > events . commit , & popup - > commit ) ;
popup - > destroy . notify = xdg_popup_destroy ;
wl_signal_add ( & xdg_popup - > events . destroy , & popup - > destroy ) ;
}
}
int main ( int argc , char * argv [ ] ) {
int main ( int argc , char * argv [ ] ) {