From acdeadcb1d83f83f8a99f753fa772bd61ae7b1ce Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 09:51:35 -0700 Subject: [PATCH 1/8] fix build --- stdlib/src/tkinter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 242570b410..e579c10b5e 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -125,7 +125,7 @@ mod _tkinter { interactive: i32, #[pyarg(any)] wantobjects: i32, - #[pyarg(any, default = "true")] + #[pyarg(any, default = true)] want_tk: bool, #[pyarg(any)] sync: i32, From 4a0c51a0da5706eb1b750218c3d213a90d10cc32 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:01:58 -0700 Subject: [PATCH 2/8] fix usage of Tcl_GetVar2Ex Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index e579c10b5e..527ca4910a 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -306,6 +306,8 @@ mod _tkinter { let threaded = { let part1 = String::from("tcl_platform"); let part2 = String::from("threaded"); + let part1 = ffi::CString::new(part1).unwrap(); + let part2 = ffi::CString::new(part2).unwrap(); let part1_ptr = part1.as_ptr(); let part2_ptr = part2.as_ptr(); tk_sys::Tcl_GetVar2Ex( From e46f0336d8859381e50d35ea80da839b64b76fe7 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:02:26 -0700 Subject: [PATCH 3/8] no panic on mainloop Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 527ca4910a..a25fa0fa88 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -289,7 +289,19 @@ mod _tkinter { #[pymethod] fn mainloop(&self, threshold: Option) -> PyResult<()> { let threshold = threshold.unwrap_or(0); - todo!(); + // self.dispatching = true; + QUIT_MAIN_LOOP.store(false, Ordering::Relaxed); + while unsafe { tk_sys::Tk_GetNumMainWindows() } > threshold && !QUIT_MAIN_LOOP.load(Ordering::Relaxed) && !ERROR_IN_CMD.load(Ordering::Relaxed) { + let mut result = 0; + if self.threaded { + result = unsafe { tk_sys::Tcl_DoOneEvent(0 as _) } as i32; + } else { + result = unsafe { tk_sys::Tcl_DoOneEvent(tk_sys::TCL_DONT_WAIT as _) } as i32; + // TODO: sleep for the proper time + std::thread::sleep(std::time::Duration::from_millis(1)); + } + } + Ok(()) } #[pymethod] From 4a88e3c3e818c697956c16c97aebe862714995d2 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:02:43 -0700 Subject: [PATCH 4/8] add static var Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index a25fa0fa88..b997b22c1c 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -72,6 +72,7 @@ mod _tkinter { impl TclObject {} static QUIT_MAIN_LOOP: AtomicBool = AtomicBool::new(false); + static ERROR_IN_CMD: AtomicBool = AtomicBool::new(false); #[pyattr] #[pyclass(name = "tkapp")] From 41a921b9b90d0954f4f17bbf2f678ccb29bd53e1 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:03:05 -0700 Subject: [PATCH 5/8] fix getvar Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index b997b22c1c..3a7e97298a 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -169,6 +169,14 @@ mod _tkinter { ))) } + #[derive(Debug, FromArgs)] + struct TkAppGetVarArgs { + #[pyarg(any)] + name: PyObjectRef, + #[pyarg(any, default)] + name2: Option, + } + // TODO: DISALLOW_INSTANTIATION #[pyclass(with(Constructor))] impl TkApp { @@ -249,20 +257,35 @@ mod _tkinter { } #[pymethod] - fn getvar(&self, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult { + fn getvar(&self, args: TkAppGetVarArgs, vm: &VirtualMachine) -> PyResult { + let TkAppGetVarArgs { name, name2 } = args; // TODO: technically not thread safe - let name = varname_converter(arg, vm)?; + let name = varname_converter(name, vm)?; + let name = ffi::CString::new(name).unwrap(); + let name2 = ffi::CString::new(name2.unwrap_or_default()).unwrap(); + let name2_ptr = if name2.is_empty() { + ptr::null() + } else { + name2.as_ptr() + }; let res = unsafe { tk_sys::Tcl_GetVar2Ex( self.interpreter, - ptr::null(), name.as_ptr() as _, + name2_ptr as _, tk_sys::TCL_LEAVE_ERR_MSG as _, ) }; if res == ptr::null_mut() { - todo!(); + // TODO: Should be tk error + // self.interpreter + let err_obj = tcl_sys::Tcl_GetObjResult(interp); + let err_str_obj = tcl_sys::Tcl_GetString(err_obj); + let err_cstr = CStr::from_ptr(err_msg as _); + return Err(vm.new_type_error(format!( + "{err_cstr:?}" + ))); } let res = if self.want_objects { self.from_object(res, vm) From 6ad5a90dd9c9e7b39013f2ec2ccb04ec6eca8fd2 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:11:56 -0700 Subject: [PATCH 6/8] add globalgetvar support Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 46 +++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 3a7e97298a..2c0b9ff1d0 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -256,8 +256,13 @@ mod _tkinter { Self::unicode_from_string(s, len as _, vm) } - #[pymethod] - fn getvar(&self, args: TkAppGetVarArgs, vm: &VirtualMachine) -> PyResult { + fn var_invoke(&self) { + if self.threaded && self.thread_id != unsafe { tk_sys::Tcl_GetCurrentThread() } { + // TODO: do stuff + } + } + + fn inner_getvar(&self, args: TkAppGetVarArgs, flags: u32, vm: &VirtualMachine) -> PyResult { let TkAppGetVarArgs { name, name2 } = args; // TODO: technically not thread safe let name = varname_converter(name, vm)?; @@ -274,18 +279,19 @@ mod _tkinter { self.interpreter, name.as_ptr() as _, name2_ptr as _, - tk_sys::TCL_LEAVE_ERR_MSG as _, + flags as _, ) }; if res == ptr::null_mut() { // TODO: Should be tk error - // self.interpreter - let err_obj = tcl_sys::Tcl_GetObjResult(interp); - let err_str_obj = tcl_sys::Tcl_GetString(err_obj); - let err_cstr = CStr::from_ptr(err_msg as _); - return Err(vm.new_type_error(format!( - "{err_cstr:?}" - ))); + unsafe { + let err_obj = tk_sys::Tcl_GetObjResult(self.interpreter); + let err_str_obj = tk_sys::Tcl_GetString(err_obj); + let err_cstr = ffi::CStr::from_ptr(err_str_obj as _); + return Err(vm.new_type_error(format!( + "{err_cstr:?}" + ))); + } } let res = if self.want_objects { self.from_object(res, vm) @@ -295,6 +301,26 @@ mod _tkinter { Ok(res) } + #[pymethod] + fn getvar( + &self, + args: TkAppGetVarArgs, + vm: &VirtualMachine, + ) -> PyResult { + self.var_invoke(); + self.inner_getvar(args, tk_sys::TCL_LEAVE_ERR_MSG, vm) + } + + #[pymethod] + fn globalgetvar( + &self, + args: TkAppGetVarArgs, + vm: &VirtualMachine, + ) -> PyResult { + self.var_invoke(); + self.inner_getvar(args, tk_sys::TCL_LEAVE_ERR_MSG | tk_sys::TCL_GLOBAL_ONLY, vm) + } + #[pymethod] fn getint(&self, arg: PyObjectRef, vm: &VirtualMachine) -> PyResult { if let Some(int) = arg.downcast_ref::() { From 1407613bb3d1b8e09c6bdc8ecf4ff15e29367329 Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Mon, 12 May 2025 12:22:03 -0700 Subject: [PATCH 7/8] formatting Signed-off-by: Ashwin Naren --- stdlib/src/tkinter.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 2c0b9ff1d0..0427a21371 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -262,7 +262,12 @@ mod _tkinter { } } - fn inner_getvar(&self, args: TkAppGetVarArgs, flags: u32, vm: &VirtualMachine) -> PyResult { + fn inner_getvar( + &self, + args: TkAppGetVarArgs, + flags: u32, + vm: &VirtualMachine, + ) -> PyResult { let TkAppGetVarArgs { name, name2 } = args; // TODO: technically not thread safe let name = varname_converter(name, vm)?; @@ -288,9 +293,7 @@ mod _tkinter { let err_obj = tk_sys::Tcl_GetObjResult(self.interpreter); let err_str_obj = tk_sys::Tcl_GetString(err_obj); let err_cstr = ffi::CStr::from_ptr(err_str_obj as _); - return Err(vm.new_type_error(format!( - "{err_cstr:?}" - ))); + return Err(vm.new_type_error(format!("{err_cstr:?}"))); } } let res = if self.want_objects { @@ -302,11 +305,7 @@ mod _tkinter { } #[pymethod] - fn getvar( - &self, - args: TkAppGetVarArgs, - vm: &VirtualMachine, - ) -> PyResult { + fn getvar(&self, args: TkAppGetVarArgs, vm: &VirtualMachine) -> PyResult { self.var_invoke(); self.inner_getvar(args, tk_sys::TCL_LEAVE_ERR_MSG, vm) } @@ -318,7 +317,11 @@ mod _tkinter { vm: &VirtualMachine, ) -> PyResult { self.var_invoke(); - self.inner_getvar(args, tk_sys::TCL_LEAVE_ERR_MSG | tk_sys::TCL_GLOBAL_ONLY, vm) + self.inner_getvar( + args, + tk_sys::TCL_LEAVE_ERR_MSG | tk_sys::TCL_GLOBAL_ONLY, + vm, + ) } #[pymethod] @@ -341,7 +344,10 @@ mod _tkinter { let threshold = threshold.unwrap_or(0); // self.dispatching = true; QUIT_MAIN_LOOP.store(false, Ordering::Relaxed); - while unsafe { tk_sys::Tk_GetNumMainWindows() } > threshold && !QUIT_MAIN_LOOP.load(Ordering::Relaxed) && !ERROR_IN_CMD.load(Ordering::Relaxed) { + while unsafe { tk_sys::Tk_GetNumMainWindows() } > threshold + && !QUIT_MAIN_LOOP.load(Ordering::Relaxed) + && !ERROR_IN_CMD.load(Ordering::Relaxed) + { let mut result = 0; if self.threaded { result = unsafe { tk_sys::Tcl_DoOneEvent(0 as _) } as i32; From 7e85e04cbe9f238d6cc570056d4ce98026c189ca Mon Sep 17 00:00:00 2001 From: Ashwin Naren Date: Sun, 18 May 2025 19:39:09 -0700 Subject: [PATCH 8/8] address review --- stdlib/src/tkinter.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stdlib/src/tkinter.rs b/stdlib/src/tkinter.rs index 0427a21371..b67bc7a9ec 100644 --- a/stdlib/src/tkinter.rs +++ b/stdlib/src/tkinter.rs @@ -272,8 +272,8 @@ mod _tkinter { // TODO: technically not thread safe let name = varname_converter(name, vm)?; - let name = ffi::CString::new(name).unwrap(); - let name2 = ffi::CString::new(name2.unwrap_or_default()).unwrap(); + let name = ffi::CString::new(name)?; + let name2 = ffi::CString::new(name2.unwrap_or_default())?; let name2_ptr = if name2.is_empty() { ptr::null() } else { @@ -374,8 +374,8 @@ mod _tkinter { let threaded = { let part1 = String::from("tcl_platform"); let part2 = String::from("threaded"); - let part1 = ffi::CString::new(part1).unwrap(); - let part2 = ffi::CString::new(part2).unwrap(); + let part1 = ffi::CString::new(part1)?; + let part2 = ffi::CString::new(part2)?; let part1_ptr = part1.as_ptr(); let part2_ptr = part2.as_ptr(); tk_sys::Tcl_GetVar2Ex(