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
39be2437
Verified
Commit
39be2437
authored
May 31, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ui: improve GNOME monitor arrangement snapping
parent
ce54942e
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
87 additions
and
3 deletions
+87
-3
displays-view.vala
src/ui/displays-view.vala
+1
-0
monitor-layout.vala
src/ui/monitor-layout.vala
+86
-3
No files found.
src/ui/displays-view.vala
View file @
39be2437
...
...
@@ -33,6 +33,7 @@ namespace TunerDisplays {
layout
=
new
MonitorLayout
()
{
height_request
=
320
,
hexpand
=
true
,
require_connected
=
backend
.
id
==
"gnome"
,
can_focus
=
false
,
focusable
=
false
};
...
...
src/ui/monitor-layout.vala
View file @
39be2437
...
...
@@ -3,7 +3,9 @@ namespace TunerDisplays {
public
class
MonitorLayout
:
Gtk
.
DrawingArea
{
private
const
double
EDGE_PADDING
=
6
;
private
const
double
MARGIN_MON
=
0.66
;
private
const
double
CONNECTED_MARGIN_MON
=
1.20
;
private
const
double
SNAP_DISTANCE
=
25
;
private
const
double
MIN_OVERLAP
=
25
;
private
const
double
MIN_ZOOM
=
0.04
;
private
const
double
MAX_ZOOM
=
0.18
;
private
Gee
.
ArrayList
<
MonitorConfig
>
monitors
=
new
Gee
.
ArrayList
<
MonitorConfig
>();
...
...
@@ -17,6 +19,7 @@ namespace TunerDisplays {
private
int
drag_start_y
=
0
;
private
bool
drag_active
;
private
bool
needs_recenter
=
true
;
public
bool
require_connected
{
get
;
set
;
}
public
signal
void
layout_changed
();
...
...
@@ -43,7 +46,8 @@ namespace TunerDisplays {
int
next_x
=
drag_start_x
+
(
int
)
Math
.
round
(
dx
/
zoom
);
int
next_y
=
drag_start_y
+
(
int
)
Math
.
round
(
dy
/
zoom
);
snap_position
(
monitor
,
ref
next_x
,
ref
next_y
);
clamp_position
(
monitor
,
ref
next_x
,
ref
next_y
);
if
(!
require_connected
)
clamp_position
(
monitor
,
ref
next_x
,
ref
next_y
);
if
(
overlaps_any
(
monitor
,
next_x
,
next_y
))
{
next_x
=
previous_x
;
next_y
=
previous_y
;
...
...
@@ -193,6 +197,11 @@ namespace TunerDisplays {
}
private
void
snap_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
if
(
require_connected
)
{
snap_connected_position
(
monitor
,
ref
x
,
ref
y
);
return
;
}
var
width
=
get_logical_width
(
monitor
);
var
height
=
get_logical_height
(
monitor
);
var
snap_units
=
SNAP_DISTANCE
/
zoom
;
...
...
@@ -227,6 +236,70 @@ namespace TunerDisplays {
y
=
snapped_y
;
}
private
void
snap_connected_position
(
MonitorConfig
monitor
,
ref
int
x
,
ref
int
y
)
{
var
width
=
get_logical_width
(
monitor
);
var
height
=
get_logical_height
(
monitor
);
var
snap_units
=
enabled_count
()
<=
2
?
double
.
MAX
:
SNAP_DISTANCE
/
zoom
;
double
best_distance
=
double
.
MAX
;
int
best_x
=
x
;
int
best_y
=
y
;
var
current_right
=
x
+
width
;
var
current_bottom
=
y
+
height
;
foreach
(
var
other
in
monitors
)
{
if
(
other
==
monitor
||
!
other
.
enabled
)
continue
;
var
other_width
=
get_logical_width
(
other
);
var
other_height
=
get_logical_height
(
other
);
var
other_right
=
other
.
x
+
other_width
;
var
other_bottom
=
other
.
y
+
other_height
;
var
top
=
(
int
)
Math
.
round
(
other
.
y
-
height
);
var
bottom
=
(
int
)
Math
.
round
(
other
.
y
+
other_height
);
var
left
=
(
int
)
Math
.
round
(
other
.
x
-
width
);
var
right
=
(
int
)
Math
.
round
(
other
.
x
+
other_width
);
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
);
consider_position
(
x
,
y
,
x
,
bottom
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
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
);
consider_position
(
x
,
y
,
right
,
y
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
if
(
enabled_count
()
<=
2
)
{
consider_position
(
x
,
y
,
(
int
)
Math
.
round
(
other
.
x
-
width
+
MIN_OVERLAP
),
top
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
(
int
)
Math
.
round
(
other
.
x
+
other_width
-
MIN_OVERLAP
),
top
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
(
int
)
Math
.
round
(
other
.
x
-
width
+
MIN_OVERLAP
),
bottom
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
(
int
)
Math
.
round
(
other
.
x
+
other_width
-
MIN_OVERLAP
),
bottom
,
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
left
,
(
int
)
Math
.
round
(
other
.
y
-
height
+
MIN_OVERLAP
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
left
,
(
int
)
Math
.
round
(
other
.
y
+
other_height
-
MIN_OVERLAP
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
right
,
(
int
)
Math
.
round
(
other
.
y
-
height
+
MIN_OVERLAP
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
consider_position
(
x
,
y
,
right
,
(
int
)
Math
.
round
(
other
.
y
+
other_height
-
MIN_OVERLAP
),
snap_units
,
ref
best_distance
,
ref
best_x
,
ref
best_y
);
}
}
x
=
best_x
;
y
=
best_y
;
}
private
static
bool
ranges_overlap
(
double
a1
,
double
a2
,
double
b1
,
double
b2
)
{
return
a1
<=
b2
&&
b1
<=
a2
;
}
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
dy
=
Math
.
fabs
(
y
-
candidate_y
);
var
distance
=
double
.
max
(
dx
,
dy
);
if
(
distance
<=
threshold
&&
distance
<
best_distance
)
{
best_distance
=
distance
;
best_x
=
candidate_x
;
best_y
=
candidate_y
;
}
}
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
)
{
...
...
@@ -285,6 +358,15 @@ namespace TunerDisplays {
return
ax
<
bx
+
bw
&&
ax
+
aw
>
bx
&&
ay
<
by
+
bh
&&
ay
+
ah
>
by
;
}
private
int
enabled_count
()
{
int
count
=
0
;
foreach
(
var
monitor
in
monitors
)
{
if
(
monitor
.
enabled
)
count
++;
}
return
count
;
}
private
void
normalize_positions
()
{
if
(
monitors
.
size
==
0
)
return
;
...
...
@@ -350,8 +432,9 @@ namespace TunerDisplays {
var
layout_width
=
double
.
max
(
1
,
max_x
-
min_x
);
var
layout_height
=
double
.
max
(
1
,
max_y
-
min_y
);
var
fit_x
=
width
/
(
layout_width
+
max_monitor_width
*
2
*
MARGIN_MON
);
var
fit_y
=
height
/
(
layout_height
+
max_monitor_height
*
2
*
MARGIN_MON
);
var
margin
=
require_connected
?
CONNECTED_MARGIN_MON
:
MARGIN_MON
;
var
fit_x
=
width
/
(
layout_width
+
max_monitor_width
*
2
*
margin
);
var
fit_y
=
height
/
(
layout_height
+
max_monitor_height
*
2
*
margin
);
zoom
=
double
.
min
(
MAX_ZOOM
,
double
.
max
(
MIN_ZOOM
,
double
.
min
(
fit_x
,
fit_y
)));
offset_x
=
width
/
2.0
-
((
min_x
+
max_x
)
/
2.0
)
*
zoom
;
offset_y
=
height
/
2.0
-
((
min_y
+
max_y
)
/
2.0
)
*
zoom
;
...
...
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