Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6f94f63

Browse files
committed
feat(power-menu): enhance keyboard navigation and focus management
Added keyboard navigation support for the power menu buttons, allowing users to navigate through buttons using arrow keys and trigger actions with Enter or Space.
1 parent432c880 commit6f94f63

File tree

1 file changed

+115
-8
lines changed

1 file changed

+115
-8
lines changed

‎src/core/widgets/yasb/power_menu.py

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
importsys
21
fromPyQt6.QtWidgetsimportQApplication,QWidget,QPushButton,QVBoxLayout,QHBoxLayout,QLabel,QStyleOption,QStyle
32
fromPyQt6importQtCore,QtGui
43
fromPyQt6.QtGuiimportQCursor
@@ -154,11 +153,19 @@ def show_main_window(self):
154153

155154

156155
classMainWindow(BaseStyledWidget,AnimatedWidget):
157-
def__init__(self,parent_button,uptime,blur,blur_background,animation_duration,button_row,buttons):
156+
def__init__(self,parent_button,uptime,blur,blur_background,animation_duration,button_row,buttons):
158157
super(MainWindow,self).__init__(animation_duration)
159158

160159
self.overlay=OverlayWidget(animation_duration,uptime)
161160
self.parent_button=parent_button
161+
self.button_row=button_row# Store button_row as instance attribute
162+
163+
# Add focus policy to allow keyboard focus
164+
self.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
165+
166+
# Initialize variables to track focused button
167+
self.buttons_list= []
168+
self.current_focus_index=-1
162169

163170
self.setProperty("class","power-menu-popup")
164171
self.setWindowFlags(Qt.WindowType.FramelessWindowHint|Qt.WindowType.WindowStaysOnTopHint|Qt.WindowType.Tool)
@@ -175,8 +182,6 @@ def __init__(self, parent_button, uptime,blur, blur_background, animation_durati
175182
icon,text=button_info
176183
self.buttons_info.append((icon,text,action_method,button_name))
177184

178-
179-
180185
main_layout=QVBoxLayout()
181186
button_layout1=QHBoxLayout()
182187
button_layout2=QHBoxLayout()
@@ -190,6 +195,9 @@ def __init__(self, parent_button, uptime,blur, blur_background, animation_durati
190195
button.setProperty("class",f"button{class_name}")
191196
button_layout=QVBoxLayout(button)
192197

198+
# Store buttons in a list for navigation
199+
self.buttons_list.append(button)
200+
193201
# Only add icon label if icon is not empty or None
194202
ificon:
195203
icon_label=QLabel(f'{icon}',self)
@@ -214,6 +222,7 @@ def __init__(self, parent_button, uptime,blur, blur_background, animation_durati
214222

215223
button.clicked.connect(action)
216224
button.installEventFilter(self)
225+
217226

218227
main_layout.addLayout(button_layout1)
219228
main_layout.addLayout(button_layout2)
@@ -241,7 +250,6 @@ def __init__(self, parent_button, uptime,blur, blur_background, animation_durati
241250
BorderColor="None"
242251
)
243252

244-
245253
self.fade_in()
246254

247255
defcenter_on_screen(self):
@@ -255,7 +263,6 @@ def center_on_screen(self):
255263
self.move(x,y)
256264
self.overlay.update_geometry(screen_geometry)# Update overlay geometry to match screen
257265

258-
259266
defpaintEvent(self,event):
260267
option=QStyleOption()
261268
option.initFrom(self)
@@ -276,7 +283,107 @@ def eventFilter(self, source, event):
276283
defkeyPressEvent(self,event):
277284
ifevent.key()==Qt.Key.Key_Escape:
278285
self.cancel_action()
279-
super(MainWindow,self).keyPressEvent(event)
286+
event.accept()# Mark event as handled
287+
elifevent.key()==Qt.Key.Key_Right:
288+
self.navigate_focus(1)
289+
event.accept()# Mark event as handled
290+
elifevent.key()==Qt.Key.Key_Left:
291+
self.navigate_focus(-1)
292+
event.accept()# Mark event as handled
293+
elifevent.key()==Qt.Key.Key_Down:
294+
self.navigate_focus(self.button_row)
295+
event.accept()# Mark event as handled
296+
elifevent.key()==Qt.Key.Key_Up:
297+
self.navigate_focus(-self.button_row)
298+
event.accept()# Mark event as handled
299+
elifevent.key()in (Qt.Key.Key_Return,Qt.Key.Key_Enter,Qt.Key.Key_Space):
300+
# Trigger click on the focused button
301+
if0<=self.current_focus_index<len(self.buttons_list):
302+
self.buttons_list[self.current_focus_index].click()
303+
event.accept()# Mark event as handled
304+
else:
305+
super(MainWindow,self).keyPressEvent(event)
306+
307+
defnavigate_focus(self,step):
308+
"""Navigate button focus by step."""
309+
ifnotself.buttons_list:
310+
return
311+
312+
total_buttons=len(self.buttons_list)
313+
314+
# If no button is currently focused, start with the appropriate first button
315+
ifself.current_focus_index<0orself.current_focus_index>=total_buttons:
316+
ifstep>0:
317+
# When pressing right arrow with no selection, select the first button
318+
new_index=0
319+
elifstep<0:
320+
# When pressing left arrow with no selection, select the last button
321+
new_index=total_buttons-1
322+
else:
323+
# For other keys with no selection, default to first button
324+
new_index=0
325+
else:
326+
# Normal navigation with existing selection
327+
current=self.current_focus_index
328+
329+
# Simple navigation with wrapping
330+
ifstep==1:# Right
331+
new_index= (current+1)%total_buttons
332+
elifstep==-1:# Left
333+
new_index= (current-1)%total_buttons
334+
elifstep==self.button_row:# Down
335+
new_index= (current+self.button_row)%total_buttons
336+
elifstep==-self.button_row:# Up
337+
new_index= (current-self.button_row)%total_buttons
338+
else:
339+
new_index=current# No change
340+
341+
self.set_focused_button(new_index)
342+
343+
defset_focused_button(self,index):
344+
"""Set focus to the button at the given index."""
345+
ifnotself.buttons_list:
346+
return
347+
348+
# Safety check - ensure index is valid
349+
ifindex<0orindex>=len(self.buttons_list):
350+
return
351+
352+
# Update our internal tracking
353+
self.current_focus_index=index
354+
355+
# First, remove hover from all buttons
356+
fori,buttoninenumerate(self.buttons_list):
357+
# Parse class components
358+
class_parts=button.property('class').split()
359+
# Remove any hover class if present
360+
if'hover'inclass_parts:
361+
class_parts.remove('hover')
362+
# Set class without hover
363+
clean_class=' '.join(class_parts)
364+
button.setProperty("class",clean_class)
365+
button.style().unpolish(button)
366+
button.style().polish(button)
367+
368+
# Then apply hover to the selected button
369+
current_button=self.buttons_list[self.current_focus_index]
370+
current_class=current_button.property('class')
371+
372+
# Add hover class
373+
hover_class=f"{current_class} hover"
374+
current_button.setProperty("class",hover_class)
375+
current_button.style().unpolish(current_button)
376+
current_button.style().polish(current_button)
377+
378+
self.setFocus()
379+
380+
defshowEvent(self,event):
381+
"""Override show event to set focus."""
382+
super(MainWindow,self).showEvent(event)
383+
# Set focus to the window and first button when shown
384+
self.setFocus()
385+
self.current_focus_index=-1
386+
280387

281388
defsignout_action(self):
282389
self.power_operations.signout()
@@ -303,4 +410,4 @@ def hibernate_action(self):
303410
self.power_operations.hibernate()
304411

305412
defcancel_action(self):
306-
self.power_operations.cancel()
413+
self.power_operations.cancel()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp