Skip to content

Commit 82d7e07

Browse files
committed
Rework window selector
1 parent 342a75f commit 82d7e07

File tree

2 files changed

+140
-120
lines changed

2 files changed

+140
-120
lines changed

Source/ide/simba.ide_maintoolbar.pas

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -209,28 +209,8 @@ procedure TSimbaMainToolBar.DoClickAreaSelector(Sender: TObject);
209209
end;
210210

211211
procedure TSimbaMainToolBar.DoClickWindowSelector(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
212-
var
213-
Path, Bitness: String;
214212
begin
215-
try
216-
FWindowSelection := ShowWindowSelector();
217-
FProcessSelection := FWindowSelection.GetPID();
218-
219-
Path := GetProcessPath(FProcessSelection);
220-
Bitness := IfThen(IsProcess64Bit(FProcessSelection), '64 bit', '32 bit');
221-
222-
DebugLn([EDebugLn.FOCUS], 'Window Selected: %d', [FWindowSelection]);
223-
DebugLn([EDebugLn.FOCUS], ' - Dimensions: %dx%d', [FWindowSelection.GetBounds().Width - 1, FWindowSelection.GetBounds().Height - 1]);
224-
DebugLn([EDebugLn.FOCUS], ' - Title: "%s"', [FWindowSelection.GetTitle()]);
225-
DebugLn([EDebugLn.FOCUS], ' - Class: "%s"', [FWindowSelection.GetClassName()]);
226-
DebugLn([EDebugLn.FOCUS], ' - PID: %d (%s)', [FProcessSelection, Bitness]);
227-
DebugLn([EDebugLn.FOCUS], ' - Executable: "%s"', [Path]);
228-
229-
SimbaIDEEvents.Notify(SimbaIDEEvent.WINDOW_SELECTED, Self);
230-
except
231-
on E: Exception do
232-
ShowMessage('Exception while picking color: ' + E.Message);
233-
end;
213+
SimbaWindowSelector.Pick();
234214
end;
235215

236216
procedure TSimbaMainToolBar.DoSettingChanged_Spacing(Setting: TSimbaSetting);

Source/ide/simba.ide_windowselector.pas

Lines changed: 139 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,21 @@
1313
interface
1414

1515
uses
16-
classes, sysutils, controls, forms, graphics,
17-
simba.base;
16+
Classes, SysUtils, Controls, Forms, Graphics,
17+
simba.base,
18+
simba.ide_events;
1819

19-
function ShowWindowSelector: TWindowHandle;
20+
type
21+
TSimbaWindowSelector = class(TObject)
22+
public
23+
constructor Create;
24+
destructor Destroy; override;
25+
26+
procedure Pick;
27+
end;
28+
29+
var
30+
SimbaWindowSelector: TSimbaWindowSelector;
2031

2132
implementation
2233

@@ -27,81 +38,40 @@ implementation
2738
{$IFDEF DARWIN}
2839
CocoaAll, CocoaWSForms, CocoaUtils,
2940
{$ENDIF}
30-
simba.baseclass, simba.vartype_windowhandle, simba.nativeinterface;
41+
simba.ide_maintoolbar,
42+
simba.vartype_windowhandle,
43+
simba.vartype_box,
44+
simba.process,
45+
simba.dialog,
46+
simba.nativeinterface,
47+
simba.initializations;
3148

3249
type
33-
TSimbaWindowSelectorBase = class(TSimbaBaseClass)
34-
protected
35-
FExcludeWindows: TWindowHandleArray;
36-
37-
procedure HighlightWindow(Window: TWindowHandle); virtual; abstract;
38-
public
39-
function Select: TWindowHandle;
40-
end;
41-
42-
// 4 forms to create a box around the window
43-
TSimbaWindowSelectorSimple = class(TSimbaWindowSelectorBase)
44-
protected
45-
const
46-
BORDER_SIZE = 4;
47-
protected
48-
FLeftForm, FRightForm, FTopForm, FBottomForm: TForm;
49-
50-
procedure HighlightWindow(Window: TWindowHandle); override;
51-
public
52-
constructor Create;
53-
destructor Destroy; override;
54-
end;
55-
56-
// overlay a transparent form
57-
TSimbaWindowSelectorFancy = class(TSimbaWindowSelectorBase)
50+
TWindowHighlighter = class
51+
protected const
52+
BORDER_SIZE = 3;
5853
protected
5954
FForm: TForm;
60-
61-
procedure HighlightWindow(Window: TWindowHandle); override;
55+
FLeftForm, FRightForm, FTopForm, FBottomForm: TForm;
56+
FExcludeWindows: TWindowHandleArray;
6257
public
6358
constructor Create;
6459
destructor Destroy; override;
65-
end;
6660

67-
function ShowWindowSelector: TWindowHandle;
68-
begin
69-
// Linux (xlib) does support transparent windows but display managers may or may not perform.
70-
{$IF DEFINED(WINDOWS) or DEFINED(DARWIN)}
71-
with TSimbaWindowSelectorFancy.Create() do
72-
{$ELSE}
73-
with TSimbaWindowSelectorSimple.Create() do
74-
{$ENDIF}
75-
try
76-
Result := Select();
77-
finally
78-
Free();
61+
function GetWindowAtCursor: TWindowHandle;
62+
procedure Highlight(Window: TWindowHandle);
7963
end;
80-
end;
8164

82-
function TSimbaWindowSelectorBase.Select: TWindowHandle;
83-
var
84-
Window: TWindowHandle;
85-
begin
86-
Result := 0;
65+
constructor TWindowHighlighter.Create;
8766

88-
while SimbaNativeInterface.MousePressed(EMouseButton.LEFT) do
67+
function FormToWindowHandle(Form: TForm): TWindowHandle;
8968
begin
90-
Window := GetWindowAtCursor(FExcludeWindows);
91-
if (Window <> 0) and (Window <> Result) then
92-
begin
93-
HighlightWindow(Window);
94-
95-
Result := Window;
96-
end;
97-
98-
Application.ProcessMessages();
99-
100-
Sleep(25);
69+
{$IFDEF DARWIN}
70+
Result := TCocoaWSCustomForm.GetWindowContentFromHandle(Form).window.windowNumber;
71+
{$ELSE}
72+
Result := Form.Handle;
73+
{$ENDIF}
10174
end;
102-
end;
103-
104-
constructor TSimbaWindowSelectorSimple.Create;
10575

10676
function CreateEdgeForm: TForm;
10777
begin
@@ -114,20 +84,49 @@ constructor TSimbaWindowSelectorSimple.Create;
11484
Result.SetBounds(0, 0, 0, 0);
11585
Result.Show();
11686

117-
FExcludeWindows := FExcludeWindows + [Result.Handle];
87+
FExcludeWindows := FExcludeWindows + [FormToWindowHandle(Result)];
88+
end;
89+
90+
function CreateTransparentForm: TForm;
91+
begin
92+
Result := TForm.CreateNew(nil);
93+
Result.FormStyle := fsSystemStayOnTop;
94+
Result.BorderStyle := bsNone;
95+
Result.Scaled := False;
96+
Result.SetBounds(0, 0, 0, 0);
97+
Result.Color := clGreen;
98+
Result.AlphaBlend := True;
99+
Result.AlphaBlendValue := 100;
100+
Result.Show();
101+
102+
{$IFDEF DARWIN}
103+
with TCocoaWSCustomForm.GetWindowContentFromHandle(Result) do
104+
window.setBackgroundColor(ColorToNSColor(Result.Color));
105+
{$ENDIF}
106+
107+
{$IFDEF WINDOWS}
108+
SetWindowLong(Result.Handle, GWL_EXSTYLE, GetWindowLong(Result.Handle, GWL_EXSTYLE) or WS_EX_LAYERED or WS_EX_TRANSPARENT);
109+
{$ENDIF}
110+
111+
FExcludeWindows := FExcludeWindows + [FormToWindowHandle(Result)];
118112
end;
119113

120114
begin
121115
inherited Create();
122116

117+
{$IF DEFINED(WINDOWS) or DEFINED(DARWIN)}
118+
FForm := CreateTransparentForm();
119+
{$ELSE}
123120
FLeftForm := CreateEdgeForm();
124121
FRightForm := CreateEdgeForm();
125122
FTopForm := CreateEdgeForm();
126123
FBottomForm := CreateEdgeForm();
124+
{$ENDIF}
127125
end;
128126

129-
destructor TSimbaWindowSelectorSimple.Destroy;
127+
destructor TWindowHighlighter.Destroy;
130128
begin
129+
FreeAndNil(FForm);
131130
FreeAndNil(FLeftForm);
132131
FreeAndNil(FRightForm);
133132
FreeAndNil(FTopForm);
@@ -136,57 +135,98 @@ destructor TSimbaWindowSelectorSimple.Destroy;
136135
inherited Destroy();
137136
end;
138137

139-
procedure TSimbaWindowSelectorSimple.HighlightWindow(Window: TWindowHandle);
138+
function TWindowHighlighter.GetWindowAtCursor: TWindowHandle;
139+
begin
140+
Result := SimbaNativeInterface.GetWindowAtCursor(FExcludeWindows);
141+
end;
142+
143+
procedure TWindowHighlighter.Highlight(Window: TWindowHandle);
140144
begin
141145
with Window.GetBounds() do
142146
begin
143-
FLeftForm.SetBounds(X1 - BORDER_SIZE, Y1 - BORDER_SIZE, BORDER_SIZE, Y2 - Y1 + (BORDER_SIZE * 2));
144-
FRightForm.SetBounds(X2, Y1 - BORDER_SIZE, BORDER_SIZE, Y2 - Y1 + (BORDER_SIZE * 2));
145-
FTopForm.SetBounds(X1, Y1 - BORDER_SIZE, X2 - X1, BORDER_SIZE);
146-
FBottomForm.SetBounds(X1, Y2, X2 - X1, BORDER_SIZE);
147+
if (FForm <> nil) then FForm.SetBounds(X1, Y1, X2 - X1, Y2 - Y1);
148+
if (FLeftForm <> nil) then FLeftForm.SetBounds(X1 - BORDER_SIZE, Y1 - BORDER_SIZE, BORDER_SIZE, Y2 - Y1 + (BORDER_SIZE * 2));
149+
if (FRightForm <> nil) then FRightForm.SetBounds(X2, Y1 - BORDER_SIZE, BORDER_SIZE, Y2 - Y1 + (BORDER_SIZE * 2));
150+
if (FTopForm <> nil) then FTopForm.SetBounds(X1, Y1 - BORDER_SIZE, X2 - X1, BORDER_SIZE);
151+
if (FBottomForm <> nil) then FBottomForm.SetBounds(X1, Y2, X2 - X1, BORDER_SIZE);
147152
end;
148153
end;
149154

150-
procedure TSimbaWindowSelectorFancy.HighlightWindow(Window: TWindowHandle);
155+
constructor TSimbaWindowSelector.Create;
151156
begin
152-
with Window.GetBounds() do
153-
FForm.SetBounds(X1, Y1, X2-X1, Y2-Y1);
157+
inherited Create();
154158
end;
155159

156-
constructor TSimbaWindowSelectorFancy.Create;
160+
destructor TSimbaWindowSelector.Destroy;
157161
begin
158-
FForm := TForm.CreateNew(nil);
159-
FForm.FormStyle := fsSystemStayOnTop;
160-
FForm.BorderStyle := bsNone;
161-
FForm.Scaled := False;
162-
FForm.SetBounds(0, 0, 0, 0);
163-
FForm.Color := clGreen;
164-
FForm.AlphaBlend := True;
165-
FForm.AlphaBlendValue := 100;
166-
FForm.Show();
162+
inherited Destroy();
163+
end;
167164

168-
{$IFDEF DARWIN}
169-
with TCocoaWSCustomForm.GetWindowContentFromHandle(FForm) do
170-
begin
171-
window.setBackgroundColor(ColorToNSColor(FForm.Color));
165+
procedure TSimbaWindowSelector.Pick;
166+
var
167+
Selected, WinAtCursor: TWindowHandle;
168+
Highlighter: TWindowHighlighter;
169+
Pid: TProcessID;
170+
Bounds: TBox;
171+
begin
172+
Selected := 0;
173+
Highlighter := nil;
174+
try
175+
Highlighter := TWindowHighlighter.Create();
172176

173-
FExcludeWindows := [window.windowNumber];
174-
end;
175-
{$ENDIF}
177+
while SimbaNativeInterface.MousePressed(EMouseButton.LEFT) do
178+
begin
179+
WinAtCursor := Highlighter.GetWindowAtCursor();
180+
if (WinAtCursor <> 0) and (WinAtCursor <> Selected) then
181+
begin
182+
Highlighter.Highlight(WinAtCursor);
183+
Selected := WinAtCursor;
184+
end;
185+
186+
Application.ProcessMessages();
187+
Sleep(25);
188+
end;
176189

177-
{$IFDEF WINDOWS}
178-
SetWindowLong(FForm.Handle, GWL_EXSTYLE, GetWindowLong(FForm.Handle, GWL_EXSTYLE) or WS_EX_LAYERED or WS_EX_TRANSPARENT);
190+
if (Selected <> 0) and Selected.IsValid() then
191+
begin
192+
Pid := Selected.GetPID();
193+
Bounds := Selected.GetBounds();
179194

180-
FExcludeWindows := [FForm.Handle];
181-
{$ENDIF}
195+
DebugLn([EDebugLn.FOCUS], 'Window Selected: %d', [Selected]);
196+
DebugLn([EDebugLn.FOCUS], ' - Dimensions: %dx%d', [Bounds.Width - 1, Bounds.Height - 1]);
197+
DebugLn([EDebugLn.FOCUS], ' - PID: %d (%s)', [PID, IfThen(IsProcess64Bit(PID), '64 bit', '32 bit')]);
198+
DebugLn([EDebugLn.FOCUS], ' - Title: "%s"', [Selected.GetTitle()]);
199+
DebugLn([EDebugLn.FOCUS], ' - ClassName: "%s"', [Selected.GetClassName()]);
200+
DebugLn([EDebugLn.FOCUS], ' - Executable: "%s"', [GetProcessPath(PID)]);
201+
202+
SimbaMainToolBar.WindowSelection := Selected;
203+
SimbaMainToolBar.ProcessSelection := Pid;
204+
205+
SimbaIDEEvents.Notify(SimbaIDEEvent.WINDOW_SELECTED, nil);
206+
end;
207+
except
208+
on E: Exception do
209+
ShowErrorDialog('Target Selector', 'Exception occurred while selecting target %s', [E.Message]);
210+
end;
211+
212+
if (Highlighter <> nil) then
213+
Highlighter.Free();
182214
end;
183215

184-
destructor TSimbaWindowSelectorFancy.Destroy;
216+
procedure DoCreate;
185217
begin
186-
FreeAndNil(FForm);
218+
SimbaWindowSelector := TSimbaWindowSelector.Create();
219+
end;
187220

188-
inherited Destroy();
221+
procedure DoDestroy;
222+
begin
223+
FreeAndNil(SimbaWindowSelector);
189224
end;
190225

226+
initialization
227+
SimbaInitialization_Add(ESimbaInit.IDE_BEFORE_SHOW, @DoCreate, 'SimbaWindowSelector');
228+
SimbaInitialization_Add(ESimbaInit.IDE_DESTROY, @DoDestroy, 'SimbaWindowSelector');
229+
191230
end.
192231

232+

0 commit comments

Comments
 (0)