@@ -1123,7 +1123,7 @@ def on_key_press_handler(sender, app_data):
11231123 # Check for modifier keys
11241124 # Note: DearPyGUI uses different constants for modifiers
11251125 modifier_pressed = {
1126- 'ctrl' : dpg .is_key_down (dpg .mvKey_LControl ) or dpg .is_key_down (dpg .mvKey_RControl ) or (is_mac and dpg .is_key_down (dpg .mvKey_LWin )),
1126+ 'ctrl' : dpg .is_key_down (dpg .mvKey_LControl ) or dpg .is_key_down (dpg .mvKey_RControl ) or (is_mac and ( dpg .is_key_down (dpg .mvKey_LWin ) or dpg . is_key_down ( dpg . mvKey_RWin ) )),
11271127 'shift' : dpg .is_key_down (dpg .mvKey_LShift ) or dpg .is_key_down (dpg .mvKey_RShift ),
11281128 'alt' : dpg .is_key_down (dpg .mvKey_LAlt ) or dpg .is_key_down (dpg .mvKey_RAlt )
11291129 }
@@ -1135,6 +1135,10 @@ def on_key_press_handler(sender, app_data):
11351135 settings = get_settings ()
11361136 shortcuts = settings .keyboard_shortcuts
11371137
1138+ # Debug logging for spacebar and number keys
1139+ if key == dpg .mvKey_Spacebar or key in [dpg .mvKey_1 , dpg .mvKey_2 , dpg .mvKey_3 , dpg .mvKey_4 ]:
1140+ logger .info (f"KEY PRESS: key={ key } , spacebar_held={ state .spacebar_held } , current_target={ state .spacebar_target_quadrant } " )
1141+
11381142 # For arrow keys, just set flags - the main loop will handle continuous movement
11391143 if _check_shortcut_match (key , modifier_pressed , shortcuts .get ('frame_back' )):
11401144 state .holding_frame_back = True
@@ -1178,59 +1182,36 @@ def on_key_press_handler(sender, app_data):
11781182 dpg .set_value (zoom_label_tag , f"{ camera .zoom_level :.2f} x" )
11791183
11801184 elif _check_shortcut_match (key , modifier_pressed , shortcuts .get ('pause_play' )):
1181- # Check if a number key (1-4) is also pressed for quadrant-specific pause
1185+ # Track that spacebar is held and update target whenever a number key changes
1186+ state .spacebar_held = True
1187+
1188+ # Check which quadrant is targeted (updates as number keys are pressed)
11821189 target_quadrant = None
1183- if dpg .is_key_down (dpg .mvKey_1 ):
1190+ if dpg .is_key_down (dpg .mvKey_1 ) or dpg . is_key_down ( dpg . mvKey_NumPad1 ) :
11841191 target_quadrant = 0
1185- elif dpg .is_key_down (dpg .mvKey_2 ):
1192+ elif dpg .is_key_down (dpg .mvKey_2 ) or dpg . is_key_down ( dpg . mvKey_NumPad2 ) :
11861193 target_quadrant = 1
1187- elif dpg .is_key_down (dpg .mvKey_3 ):
1194+ elif dpg .is_key_down (dpg .mvKey_3 ) or dpg . is_key_down ( dpg . mvKey_NumPad3 ) :
11881195 target_quadrant = 2
1189- elif dpg .is_key_down (dpg .mvKey_4 ):
1196+ elif dpg .is_key_down (dpg .mvKey_4 ) or dpg . is_key_down ( dpg . mvKey_NumPad4 ) :
11901197 target_quadrant = 3
11911198
1192- if target_quadrant is not None :
1193- logger .info (f"Keyboard: Toggle pause/play for quadrant { target_quadrant + 1 } " )
1194- else :
1195- logger .info ("Keyboard: Toggle pause/play for all cameras" )
1196-
1197- for camera in state .cameras :
1198- # Find which quadrant this camera is in
1199- cam_quadrant = None
1200- for cam_id , quad_pos in state .camera_positions .items ():
1201- if id (camera ) == cam_id :
1202- cam_quadrant = quad_pos
1203- break
1204-
1205- # Skip this camera if we're targeting a specific quadrant and this isn't it
1206- if target_quadrant is not None and cam_quadrant != target_quadrant :
1207- continue
1208-
1209- if camera .is_video_file :
1210- camera .paused = not camera .paused
1211- # Update button labels
1212- if cam_quadrant is not None :
1213- pause_btn_tag = f"pause_btn_{ cam_quadrant } "
1214- if dpg .does_item_exist (pause_btn_tag ):
1215- dpg .configure_item (pause_btn_tag , label = "Play" if camera .paused else "Pause" )
1216- elif not camera .is_video_file :
1217- # For live cameras, use toggle_live_pause() like the button does
1218- is_paused = camera .toggle_live_pause ()
1219- if cam_quadrant is not None :
1220- pause_btn_tag = f"pause_btn_{ cam_quadrant } "
1221- if dpg .does_item_exist (pause_btn_tag ):
1222- dpg .configure_item (pause_btn_tag , label = "Resume" if is_paused else "Pause" )
1223-
1224- # Show/hide slider and step buttons like the button callback does
1225- slider_tag = f"live_slider_{ cam_quadrant } "
1226- step_back_tag = f"step_back_btn_{ cam_quadrant } "
1227- step_fwd_tag = f"step_fwd_btn_{ cam_quadrant } "
1228- if dpg .does_item_exist (slider_tag ):
1229- dpg .configure_item (slider_tag , show = is_paused )
1230- if dpg .does_item_exist (step_back_tag ):
1231- dpg .configure_item (step_back_tag , show = is_paused )
1232- if dpg .does_item_exist (step_fwd_tag ):
1233- dpg .configure_item (step_fwd_tag , show = is_paused )
1199+ state .spacebar_target_quadrant = target_quadrant
1200+ logger .info (f"Spacebar PRESSED: target updated to { target_quadrant } " )
1201+
1202+ # Also update target when number keys are pressed while spacebar is held
1203+ elif state .spacebar_held and (key in [dpg .mvKey_1 , dpg .mvKey_2 , dpg .mvKey_3 , dpg .mvKey_4 ,
1204+ dpg .mvKey_NumPad1 , dpg .mvKey_NumPad2 , dpg .mvKey_NumPad3 , dpg .mvKey_NumPad4 ]):
1205+ logger .info (f"Number key detected: key={ key } , mvKey_2={ dpg .mvKey_2 } , match={ key == dpg .mvKey_2 } " )
1206+ if key == dpg .mvKey_1 or key == dpg .mvKey_NumPad1 :
1207+ state .spacebar_target_quadrant = 0
1208+ elif key == dpg .mvKey_2 or key == dpg .mvKey_NumPad2 :
1209+ state .spacebar_target_quadrant = 1
1210+ elif key == dpg .mvKey_3 or key == dpg .mvKey_NumPad3 :
1211+ state .spacebar_target_quadrant = 2
1212+ elif key == dpg .mvKey_4 or key == dpg .mvKey_NumPad4 :
1213+ state .spacebar_target_quadrant = 3
1214+ logger .info (f"Number key PRESSED while spacebar held: target updated to { state .spacebar_target_quadrant } " )
12341215
12351216 elif _check_shortcut_match (key , modifier_pressed , shortcuts .get ('record' )):
12361217 logger .info ("Keyboard: Toggle recording" )
@@ -1332,13 +1313,17 @@ def on_key_release_handler(sender, app_data):
13321313
13331314 # Check for modifier keys
13341315 modifier_pressed = {
1335- 'ctrl' : dpg .is_key_down (dpg .mvKey_LControl ) or dpg .is_key_down (dpg .mvKey_RControl ) or (is_mac and dpg .is_key_down (dpg .mvKey_LWin )),
1316+ 'ctrl' : dpg .is_key_down (dpg .mvKey_LControl ) or dpg .is_key_down (dpg .mvKey_RControl ) or (is_mac and ( dpg .is_key_down (dpg .mvKey_LWin ) or dpg . is_key_down ( dpg . mvKey_RWin ) )),
13361317 'shift' : dpg .is_key_down (dpg .mvKey_LShift ) or dpg .is_key_down (dpg .mvKey_RShift ),
13371318 'alt' : dpg .is_key_down (dpg .mvKey_LAlt ) or dpg .is_key_down (dpg .mvKey_RAlt )
13381319 }
13391320
13401321 key = app_data
13411322
1323+ # Debug logging
1324+ if key == dpg .mvKey_Spacebar :
1325+ logger .info (f"KEY RELEASE: key={ key } , spacebar_held={ state .spacebar_held } , target={ state .spacebar_target_quadrant } " )
1326+
13421327 # Load shortcuts from settings
13431328 from utils .settings import get_settings
13441329 settings = get_settings ()
@@ -1350,6 +1335,64 @@ def on_key_release_handler(sender, app_data):
13501335 elif _check_shortcut_match (key , modifier_pressed , shortcuts .get ('frame_forward' )):
13511336 state .holding_frame_forward = False
13521337
1338+ # Execute pause/play when spacebar is released (not when pressed)
1339+ # Use the target that was set during the press phase
1340+ if _check_shortcut_match (key , modifier_pressed , shortcuts .get ('pause_play' )):
1341+ # Only execute if spacebar was actually held (prevents issues with key repeat)
1342+ if not state .spacebar_held :
1343+ return
1344+
1345+ target_quadrant = state .spacebar_target_quadrant
1346+
1347+ logger .info (f"Spacebar RELEASED: using target_quadrant={ target_quadrant } " )
1348+
1349+ if target_quadrant is not None :
1350+ logger .info (f"Keyboard: Toggle pause/play for quadrant { target_quadrant + 1 } " )
1351+ else :
1352+ logger .info ("Keyboard: Toggle pause/play for all cameras" )
1353+
1354+ # Reset state for next press
1355+ state .spacebar_held = False
1356+ state .spacebar_target_quadrant = None
1357+
1358+ for camera in state .cameras :
1359+ # Find which quadrant this camera is in
1360+ cam_quadrant = None
1361+ for cam_id , quad_pos in state .camera_positions .items ():
1362+ if id (camera ) == cam_id :
1363+ cam_quadrant = quad_pos
1364+ break
1365+
1366+ # Skip this camera if we're targeting a specific quadrant and this isn't it
1367+ if target_quadrant is not None and cam_quadrant != target_quadrant :
1368+ continue
1369+
1370+ if camera .is_video_file :
1371+ camera .paused = not camera .paused
1372+ # Update button labels
1373+ if cam_quadrant is not None :
1374+ pause_btn_tag = f"pause_btn_{ cam_quadrant } "
1375+ if dpg .does_item_exist (pause_btn_tag ):
1376+ dpg .configure_item (pause_btn_tag , label = "Play" if camera .paused else "Pause" )
1377+ elif not camera .is_video_file :
1378+ # For live cameras, use toggle_live_pause() like the button does
1379+ is_paused = camera .toggle_live_pause ()
1380+ if cam_quadrant is not None :
1381+ pause_btn_tag = f"pause_btn_{ cam_quadrant } "
1382+ if dpg .does_item_exist (pause_btn_tag ):
1383+ dpg .configure_item (pause_btn_tag , label = "Resume" if is_paused else "Pause" )
1384+
1385+ # Show/hide slider and step buttons like the button callback does
1386+ slider_tag = f"live_slider_{ cam_quadrant } "
1387+ step_back_tag = f"step_back_btn_{ cam_quadrant } "
1388+ step_fwd_tag = f"step_fwd_btn_{ cam_quadrant } "
1389+ if dpg .does_item_exist (slider_tag ):
1390+ dpg .configure_item (slider_tag , show = is_paused )
1391+ if dpg .does_item_exist (step_back_tag ):
1392+ dpg .configure_item (step_back_tag , show = is_paused )
1393+ if dpg .does_item_exist (step_fwd_tag ):
1394+ dpg .configure_item (step_fwd_tag , show = is_paused )
1395+
13531396
13541397def register_global_mouse_handlers ():
13551398 """Register global mouse and keyboard handlers"""
0 commit comments