Skip to content

Commit 9cb1e1b

Browse files
committed
Add option to disable centering on current mouse pos when mouse within window rect.
1 parent a7d816c commit 9cb1e1b

File tree

2 files changed

+45
-13
lines changed

2 files changed

+45
-13
lines changed

src/gui/on_spawn_manager.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class OnSpawnSettings(TypedDict):
1818
capture_snapshot: bool | int # 0/False: disable, 1/True: capture, 2: update
1919
skip_non_resizable: bool
2020
match_resizability: bool
21+
fuzzy_mtm: bool
2122

2223

2324
class OnSpawnPage(wx.Panel):
@@ -34,19 +35,28 @@ def __init__(self, parent: wx.Frame):
3435
capture_snapshot=2,
3536
skip_non_resizable=False,
3637
match_resizability=True,
38+
fuzzy_mtm=True,
3739
)
3840
self.settings.update(OnSpawnSettings(**self.settings_file.get('on_window_spawn', default={})))
3941

42+
def header(text: str):
43+
txt = wx.StaticText(self.panel, label=text)
44+
txt.SetFont(wx.Font(12, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
45+
return txt
46+
4047
# create widgets
4148
enable_opt = wx.CheckBox(self, id=1, label='React to new windows being created')
4249
enable_opt.SetToolTip('It\'s recommended to disable "Prune window history" when this is enabled')
4350
self.panel = wx.Panel(self)
44-
header1 = wx.StaticText(self.panel, label='When a new window is created:')
51+
header1 = header('When a new window spawns:')
52+
53+
# reused later on in Misc settings.
54+
mtm_opt_name = 'Center on current mouse position'
4555

4656
option_mapping: dict[str, OnSpawnOperations] = {
4757
'Apply last known size and/or position': 'apply_lkp',
4858
'Apply compatible rules': 'apply_rules',
49-
'Center on current mouse position': 'move_to_mouse',
59+
mtm_opt_name: 'move_to_mouse',
5060
}
5161
self.rc_opt = RearrangeListCtrl(
5262
self.panel,
@@ -55,16 +65,20 @@ def __init__(self, parent: wx.Frame):
5565
label_mapping=option_mapping,
5666
)
5767

58-
ignore_children_opt = wx.CheckBox(self.panel, id=5, label='Ignore child windows')
59-
ignore_children_opt.SetToolTip(
60-
'Child windows are typically small popup windows and spawn near where the cursor is.'
61-
'\nDisabling this means such windows will be moved to the top left corner of the parent window.'
62-
# ^ this may not be accurate. TODO: remove or implement this
63-
)
68+
header2 = header('After a new window spawns:')
69+
6470
update_snapshot_opt = wx.RadioButton(self.panel, id=6, label='Update the current snapshot', style=wx.RB_GROUP)
6571
capture_snapshot_opt = wx.RadioButton(self.panel, id=7, label='Capture a new snapshot')
6672
do_nothing_opt = wx.RadioButton(self.panel, id=8, label='Do nothing')
6773

74+
header3 = header('Window filtering controls:')
75+
76+
ignore_children_opt = wx.CheckBox(self.panel, id=5, label='Ignore child windows')
77+
ignore_children_opt.SetToolTip(
78+
'Child windows are typically small popup windows that spawn near the cursor.'
79+
# '\nDisabling this means such windows will be moved to the top left corner of the parent window.'
80+
# ^ this may not be accurate. TODO: remove or implement this
81+
)
6882
skip_non_resizable_opt = wx.CheckBox(self.panel, id=9, label='Ignore non-resizable windows')
6983
skip_non_resizable_opt.SetToolTip(
7084
'Non resizable windows often include splash screens, alerts and notifications. Enable this to'
@@ -80,6 +94,12 @@ def __init__(self, parent: wx.Frame):
8094
'\nThis prevents splash screens from dictating the final window size.'
8195
)
8296

97+
header4 = header('Misc')
98+
99+
fuzzy_mtm_opt = wx.CheckBox(
100+
self.panel, id=11, label=f'Disable "{mtm_opt_name}" when mouse is already within the window'
101+
)
102+
83103
# set state
84104
enable_opt.SetValue(self.settings['enabled'])
85105
if not self.settings['enabled']:
@@ -93,6 +113,7 @@ def __init__(self, parent: wx.Frame):
93113
[do_nothing_opt, capture_snapshot_opt, update_snapshot_opt][int(self.settings['capture_snapshot'])].SetValue(
94114
True
95115
)
116+
fuzzy_mtm_opt.SetValue(self.settings['fuzzy_mtm'])
96117

97118
skip_non_resizable_opt.SetValue(self.settings['skip_non_resizable'])
98119
match_resizability_opt.SetValue(self.settings['match_resizability'])
@@ -106,6 +127,7 @@ def __init__(self, parent: wx.Frame):
106127
do_nothing_opt,
107128
skip_non_resizable_opt,
108129
match_resizability_opt,
130+
fuzzy_mtm_opt,
109131
):
110132
widget.Bind(wx.EVT_CHECKBOX if isinstance(widget, wx.CheckBox) else wx.EVT_RADIOBUTTON, self.on_setting)
111133
self.rc_opt.Bind(EVT_REARRANGE_LIST_SELECT, self.on_setting)
@@ -116,12 +138,16 @@ def __init__(self, parent: wx.Frame):
116138
(
117139
header1,
118140
self.rc_opt,
119-
ignore_children_opt,
141+
header2,
120142
update_snapshot_opt,
121143
capture_snapshot_opt,
122144
do_nothing_opt,
145+
header3,
146+
ignore_children_opt,
123147
skip_non_resizable_opt,
124148
match_resizability_opt,
149+
header4,
150+
fuzzy_mtm_opt,
125151
),
126152
group_mode=wx.HORIZONTAL,
127153
)
@@ -143,6 +169,7 @@ def on_setting(self, event: wx.Event):
143169
5: 'ignore_children',
144170
9: 'skip_non_resizable',
145171
10: 'match_resizability',
172+
11: 'fuzzy_mtm',
146173
}[event.Id]
147174
self.settings[key] = widget.GetValue()
148175
if event.Id == 1: # enable/disable feature

src/main.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import win32con
66
import win32gui
77

8-
from common import Window, load_json, local_path, single_call
8+
from common import Window, XandY, load_json, local_path, single_call
99
from device import DeviceChangeCallback, DeviceChangeService
1010
from gui import TaskbarIcon, WxApp, about_dialog, radio_menu
1111
from gui.wx_app import spawn_gui
@@ -19,8 +19,7 @@ def filter(self, record):
1919
try:
2020
return not (
2121
# sometimes the record has msg, sometimes its message. Just try to catch all of them
22-
'Release ' in getattr(record, 'message', getattr(record, 'msg', ''))
23-
and record.name == 'comtypes'
22+
'Release ' in getattr(record, 'message', getattr(record, 'msg', '')) and record.name == 'comtypes'
2423
)
2524
except Exception:
2625
# sometimes (rarely) record doesn't have a `message` attr
@@ -103,6 +102,7 @@ def on_window_spawn(windows: list[Window]):
103102
rules = snap.get_rules(compatible_with=True, exclusive=True)
104103
ignore_children = on_spawn_settings.get('ignore_children', True)
105104
match_resizability = on_spawn_settings.get('match_resizability', True)
105+
fuzzy_mtm = on_spawn_settings.get('fuzzy_mtm', True)
106106

107107
# get all the operations and the order we run them
108108
operations = {
@@ -132,7 +132,12 @@ def lkp(window: Window) -> bool:
132132
return True
133133

134134
def mtm(window: Window) -> bool:
135-
window.center_on(win32gui.GetCursorPos())
135+
cursor_pos: XandY = win32gui.GetCursorPos()
136+
if fuzzy_mtm:
137+
# if cursor X between window X and X1, and cursor Y between window Y and Y1
138+
if window.rect[0] <= cursor_pos[0] <= window.rect[2] and window.rect[1] <= cursor_pos[1] <= window.rect[3]:
139+
return True
140+
window.center_on(cursor_pos)
136141
return True
137142

138143
for window in windows:

0 commit comments

Comments
 (0)