Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tuner-displays
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ximper Linux
tuner-displays
Commits
87463a2c
Verified
Commit
87463a2c
authored
Jun 15, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ui: improve monitor layout snapping
parent
ffcc0360
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
99 additions
and
45 deletions
+99
-45
monitor-layout.vala
src/ui/widgets/monitor-layout.vala
+99
-45
No files found.
src/ui/widgets/monitor-layout.vala
View file @
87463a2c
...
@@ -4,7 +4,7 @@ namespace TunerDisplays {
...
@@ -4,7 +4,7 @@ namespace TunerDisplays {
public
class
MonitorLayout
:
Gtk
.
DrawingArea
{
public
class
MonitorLayout
:
Gtk
.
DrawingArea
{
private
const
double
EDGE_PADDING
=
6
;
private
const
double
EDGE_PADDING
=
6
;
private
const
double
MARGIN_MON
=
0.66
;
private
const
double
MARGIN_MON
=
0.66
;
private
const
double
CONNECTED_MARGIN_MON
=
1.20
;
private
const
double
CONNECTED_MARGIN_MON
=
0.66
;
private
const
double
SNAP_DISTANCE
=
25
;
private
const
double
SNAP_DISTANCE
=
25
;
private
const
double
MIN_OVERLAP
=
25
;
private
const
double
MIN_OVERLAP
=
25
;
private
const
double
MIN_ZOOM
=
0.04
;
private
const
double
MIN_ZOOM
=
0.04
;
...
@@ -211,13 +211,18 @@ namespace TunerDisplays {
...
@@ -211,13 +211,18 @@ namespace TunerDisplays {
return
;
return
;
}
}
snap_free_position
(
monitor
,
ref
x
,
ref
y
);
}
private
void
snap_free_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
var
width
=
monitor
.
logical_width
;
var
width
=
monitor
.
logical_width
;
var
height
=
monitor
.
logical_height
;
var
height
=
monitor
.
logical_height
;
var
snap_units
=
SNAP_DISTANCE
/
zoom
;
var
snap_units
=
SNAP_DISTANCE
/
zoom
;
double
best_x_distance
=
snap_units
+
1
;
double
best_distance
=
snap_units
+
1
;
double
best_y_distance
=
snap_units
+
1
;
int
best_x
=
x
;
int
snapped_x
=
x
;
int
best_y
=
y
;
int
snapped_y
=
y
;
var
right
=
x
+
width
;
var
bottom
=
y
+
height
;
foreach
(
var
other
in
monitors
)
{
foreach
(
var
other
in
monitors
)
{
if
(
other
==
monitor
)
if
(
other
==
monitor
)
...
@@ -225,24 +230,79 @@ namespace TunerDisplays {
...
@@ -225,24 +230,79 @@ namespace TunerDisplays {
var
other_width
=
other
.
logical_width
;
var
other_width
=
other
.
logical_width
;
var
other_height
=
other
.
logical_height
;
var
other_height
=
other
.
logical_height
;
var
right
=
x
+
width
;
var
bottom
=
y
+
height
;
var
other_right
=
other
.
x
+
other_width
;
var
other_right
=
other
.
x
+
other_width
;
var
other_bottom
=
other
.
y
+
other_height
;
var
other_bottom
=
other
.
y
+
other_height
;
consider_x_snap
(
x
,
other
.
x
,
ref
best_x_distance
,
ref
snapped_x
,
snap_units
);
if
(
ranges_overlap_with_margin
(
x
,
right
,
other
.
x
,
other_right
,
MIN_OVERLAP
))
{
consider_x_snap
(
x
,
(
int
)
Math
.
round
(
other_right
),
ref
best_x_distance
,
ref
snapped_x
,
snap_units
);
var
aligned_x
=
snap_parallel_position
(
x
,
width
,
other
.
x
,
other_right
,
snap_units
);
consider_x_snap
((
int
)
Math
.
round
(
right
),
other
.
x
,
ref
best_x_distance
,
ref
snapped_x
,
snap_units
,
(
int
)
Math
.
round
(-
width
));
consider_position
(
x
,
y
,
aligned_x
,
before_edge
(
other
.
y
,
height
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_x_snap
((
int
)
Math
.
round
(
right
),
(
int
)
Math
.
round
(
other_right
),
ref
best_x_distance
,
ref
snapped_x
,
snap_units
,
(
int
)
Math
.
round
(-
width
));
consider_position
(
x
,
y
,
aligned_x
,
after_edge
(
other_bottom
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
if
(
ranges_overlap_with_margin
(
y
,
bottom
,
other
.
y
,
other_bottom
,
MIN_OVERLAP
))
{
var
aligned_y
=
snap_parallel_position
(
y
,
height
,
other
.
y
,
other_bottom
,
snap_units
);
consider_position
(
x
,
y
,
before_edge
(
other
.
x
,
width
),
aligned_y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
after_edge
(
other_right
),
aligned_y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
consider_diagonal_snap
(
x
,
y
,
before_edge
(
other
.
x
,
width
),
before_edge
(
other
.
y
,
height
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_diagonal_snap
(
x
,
y
,
before_edge
(
other
.
x
,
width
),
after_edge
(
other_bottom
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_diagonal_snap
(
x
,
y
,
after_edge
(
other_right
),
before_edge
(
other
.
y
,
height
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_diagonal_snap
(
x
,
y
,
after_edge
(
other_right
),
after_edge
(
other_bottom
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
x
=
best_x
;
y
=
best_y
;
}
private
static
bool
ranges_overlap_with_margin
(
double
a1
,
double
a2
,
double
b1
,
double
b2
,
double
margin
)
{
return
double
.
min
(
a2
,
b2
)
-
double
.
max
(
a1
,
b1
)
>=
margin
;
}
private
static
int
snap_parallel_position
(
int
position
,
double
size
,
double
other_start
,
double
other_end
,
double
threshold
)
{
double
best_distance
=
threshold
+
1
;
int
best
=
position
;
consider_y_snap
(
y
,
other
.
y
,
ref
best_y_distance
,
ref
snapped_y
,
snap_units
);
consider_parallel_snap
(
position
,
(
int
)
Math
.
round
(
other_start
),
ref
best_distance
,
ref
best
,
threshold
);
consider_y_snap
(
y
,
(
int
)
Math
.
round
(
other_bottom
),
ref
best_y_distance
,
ref
snapped_y
,
snap_units
);
consider_parallel_snap
(
consider_y_snap
((
int
)
Math
.
round
(
bottom
),
other
.
y
,
ref
best_y_distance
,
ref
snapped_y
,
snap_units
,
(
int
)
Math
.
round
(-
height
));
(
int
)
Math
.
round
(
position
+
size
),
consider_y_snap
((
int
)
Math
.
round
(
bottom
),
(
int
)
Math
.
round
(
other_bottom
),
ref
best_y_distance
,
ref
snapped_y
,
snap_units
,
(
int
)
Math
.
round
(-
height
));
(
int
)
Math
.
round
(
other_end
),
ref
best_distance
,
ref
best
,
threshold
,
-(
int
)
Math
.
round
(
size
)
);
consider_parallel_snap
(
(
int
)
Math
.
round
(
position
+
size
/
2
),
(
int
)
Math
.
round
((
other_start
+
other_end
)
/
2
),
ref
best_distance
,
ref
best
,
threshold
,
-(
int
)
Math
.
round
(
size
/
2
)
);
return
best
;
}
private
static
void
consider_parallel_snap
(
int
current_edge
,
int
target_edge
,
ref
double
best_distance
,
ref
int
best
,
double
threshold
,
int
offset
=
0
)
{
var
distance
=
Math
.
fabs
(
current_edge
-
target_edge
);
if
(
distance
<=
threshold
&&
distance
<
best_distance
)
{
best_distance
=
distance
;
best
=
target_edge
+
offset
;
}
}
}
x
=
snapped_x
;
private
static
void
consider_diagonal_snap
(
int
x
,
int
y
,
int
candidate_x
,
int
candidate_y
,
double
threshold
,
ref
double
best_distance
,
ref
int
best_x
,
ref
int
best_y
)
{
y
=
snapped_y
;
var
dx
=
Math
.
fabs
(
x
-
candidate_x
);
var
dy
=
Math
.
fabs
(
y
-
candidate_y
);
if
(
dx
>
threshold
||
dy
>
threshold
)
return
;
var
distance
=
Math
.
sqrt
(
dx
*
dx
+
dy
*
dy
);
if
(
distance
<
best_distance
)
{
best_distance
=
distance
;
best_x
=
candidate_x
;
best_y
=
candidate_y
;
}
}
}
private
void
snap_connected_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
private
void
snap_connected_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
...
@@ -263,19 +323,21 @@ namespace TunerDisplays {
...
@@ -263,19 +323,21 @@ namespace TunerDisplays {
var
other_height
=
other
.
logical_height
;
var
other_height
=
other
.
logical_height
;
var
other_right
=
other
.
x
+
other_width
;
var
other_right
=
other
.
x
+
other_width
;
var
other_bottom
=
other
.
y
+
other_height
;
var
other_bottom
=
other
.
y
+
other_height
;
var
top
=
(
int
)
Math
.
round
(
other
.
y
-
height
);
var
top
=
before_edge
(
other
.
y
,
height
);
var
bottom
=
(
int
)
Math
.
round
(
other
.
y
+
other_height
);
var
bottom
=
after_edge
(
other_bottom
);
var
left
=
(
int
)
Math
.
round
(
other
.
x
-
width
);
var
left
=
before_edge
(
other
.
x
,
width
);
var
right
=
(
int
)
Math
.
round
(
other
.
x
+
other_width
);
var
right
=
after_edge
(
other_right
);
if
(
ranges_overlap
(
x
,
current_right
,
other
.
x
,
other_right
))
{
if
(
ranges_overlap
(
x
,
current_right
,
other
.
x
,
other_right
))
{
consider_position
(
x
,
y
,
x
,
top
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
var
aligned_x
=
snap_parallel_position
(
x
,
width
,
other
.
x
,
other_right
,
snap_units
);
consider_position
(
x
,
y
,
x
,
bottom
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
aligned_x
,
top
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
aligned_x
,
bottom
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
}
if
(
ranges_overlap
(
y
,
current_bottom
,
other
.
y
,
other_bottom
))
{
if
(
ranges_overlap
(
y
,
current_bottom
,
other
.
y
,
other_bottom
))
{
consider_position
(
x
,
y
,
left
,
y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
var
aligned_y
=
snap_parallel_position
(
y
,
height
,
other
.
y
,
other_bottom
,
snap_units
);
consider_position
(
x
,
y
,
right
,
y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
left
,
aligned_y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
right
,
aligned_y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
}
if
(
enabled_count
()
<=
2
)
{
if
(
enabled_count
()
<=
2
)
{
...
@@ -298,6 +360,14 @@ namespace TunerDisplays {
...
@@ -298,6 +360,14 @@ namespace TunerDisplays {
return
a1
<=
b2
&&
b1
<=
a2
;
return
a1
<=
b2
&&
b1
<=
a2
;
}
}
private
static
int
before_edge
(
double
edge
,
double
size
)
{
return
(
int
)
Math
.
floor
(
edge
-
size
);
}
private
static
int
after_edge
(
double
edge
)
{
return
(
int
)
Math
.
ceil
(
edge
);
}
private
static
void
consider_position
(
int
x
,
int
y
,
int
candidate_x
,
int
candidate_y
,
double
threshold
,
ref
double
best_distance
,
ref
int
best_x
,
ref
int
best_y
)
{
private
static
void
consider_position
(
int
x
,
int
y
,
int
candidate_x
,
int
candidate_y
,
double
threshold
,
ref
double
best_distance
,
ref
int
best_x
,
ref
int
best_y
)
{
var
dx
=
Math
.
fabs
(
x
-
candidate_x
);
var
dx
=
Math
.
fabs
(
x
-
candidate_x
);
var
dy
=
Math
.
fabs
(
y
-
candidate_y
);
var
dy
=
Math
.
fabs
(
y
-
candidate_y
);
...
@@ -309,32 +379,16 @@ namespace TunerDisplays {
...
@@ -309,32 +379,16 @@ namespace TunerDisplays {
}
}
}
}
private
static
void
consider_x_snap
(
int
current_edge
,
int
target_edge
,
ref
double
best_distance
,
ref
int
snapped_x
,
double
threshold
,
int
offset
=
0
)
{
var
distance
=
Math
.
fabs
(
current_edge
-
target_edge
);
if
(
distance
<=
threshold
&&
distance
<
best_distance
)
{
best_distance
=
distance
;
snapped_x
=
target_edge
+
offset
;
}
}
private
static
void
consider_y_snap
(
int
current_edge
,
int
target_edge
,
ref
double
best_distance
,
ref
int
snapped_y
,
double
threshold
,
int
offset
=
0
)
{
var
distance
=
Math
.
fabs
(
current_edge
-
target_edge
);
if
(
distance
<=
threshold
&&
distance
<
best_distance
)
{
best_distance
=
distance
;
snapped_y
=
target_edge
+
offset
;
}
}
private
void
clamp_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
private
void
clamp_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
if
(
view_width
<=
0
||
view_height
<=
0
||
zoom
<=
0
)
if
(
view_width
<=
0
||
view_height
<=
0
||
zoom
<=
0
)
return
;
return
;
var
logical_width
=
monitor
.
logical_width
;
var
logical_width
=
monitor
.
logical_width
;
var
logical_height
=
monitor
.
logical_height
;
var
logical_height
=
monitor
.
logical_height
;
var
min_x
=
(
EDGE_PADDING
-
offset_x
)
/
zoom
;
var
min_x
=
(
EDGE_PADDING
-
offset_x
)
/
zoom
-
logical_width
+
MIN_OVERLAP
;
var
min_y
=
(
EDGE_PADDING
-
offset_y
)
/
zoom
;
var
min_y
=
(
EDGE_PADDING
-
offset_y
)
/
zoom
-
logical_height
+
MIN_OVERLAP
;
var
max_x
=
(
view_width
-
EDGE_PADDING
-
offset_x
)
/
zoom
-
logical_width
;
var
max_x
=
(
view_width
-
EDGE_PADDING
-
offset_x
)
/
zoom
-
MIN_OVERLAP
;
var
max_y
=
(
view_height
-
EDGE_PADDING
-
offset_y
)
/
zoom
-
logical_height
;
var
max_y
=
(
view_height
-
EDGE_PADDING
-
offset_y
)
/
zoom
-
MIN_OVERLAP
;
if
(
max_x
<
min_x
)
if
(
max_x
<
min_x
)
max_x
=
min_x
;
max_x
=
min_x
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment