@@ -26,7 +26,7 @@ use std::{
2626} ;
2727use tracing:: { debug, info} ;
2828use x11:: {
29- xft:: { XftColor , XftColorAllocName , XftDrawCreate , XftDrawStringUtf8 } ,
29+ xft:: { XftColor , XftColorAllocName , XftDraw , XftDrawCreate , XftDrawDestroy , XftDrawStringUtf8 } ,
3030 xlib:: {
3131 CapButt , Complex , CoordModeOrigin , Display , Drawable , False , JoinMiter , LineSolid , Window ,
3232 XCopyArea , XCreateGC , XCreatePixmap , XDefaultColormap , XDefaultDepth , XDefaultVisual ,
@@ -419,6 +419,8 @@ impl<'a> Context<'a> {
419419 ) -> Result < ( u32 , u32 ) > {
420420 // SAFETY:
421421 // - the pointers for self.dpy and s.drawable are known to be non-null
422+ // - we wrap the returned pointer in DropXftDraw to ensure that we correctly destroy
423+ // the XftDraw we create here (see below)
422424 let d = unsafe {
423425 XftDrawCreate (
424426 self . dpy ,
@@ -428,6 +430,8 @@ impl<'a> Context<'a> {
428430 )
429431 } ;
430432
433+ let _drop_draw = DropXftDraw { ptr : d } ;
434+
431435 let ( lpad, rpad) = ( padding. 0 as i32 , padding. 1 ) ;
432436 let ( mut x, y) = ( lpad + self . dx , self . dy ) ;
433437 let ( mut total_w, mut total_h) = ( x as u32 , 0 ) ;
@@ -461,7 +465,22 @@ impl<'a> Context<'a> {
461465 total_h = max ( total_h, chunk_h) ;
462466 }
463467
464- Ok ( ( total_w + rpad, total_h) )
468+ return Ok ( ( total_w + rpad, total_h) ) ;
469+
470+ // There are multiple error paths here where we need to make sure that we correctly destroy
471+ // the XftDraw we created. Rather than complicate the error handling we use a Drop wrapper
472+ // to ensure that we run XftDrawDestroy when the function returns.
473+
474+ struct DropXftDraw {
475+ ptr : * mut XftDraw ,
476+ }
477+
478+ impl Drop for DropXftDraw {
479+ fn drop ( & mut self ) {
480+ // SAFETY: the pointer we have must be non-null
481+ unsafe { XftDrawDestroy ( self . ptr ) } ;
482+ }
483+ }
465484 }
466485
467486 /// Determine the width and height taken up by a given string in pixels.
0 commit comments