1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
--- a/src/displays.cpp
+++ b/src/displays.cpp
@@ -98,6 +98,7 @@
pack_start(heading, false, false); pack_start(description, false, false);
toolbar.pack_start(refresh_button, false, false); toolbar.pack_start(identify_button, false, false);
pack_start(toolbar, false, false);
+ diagram.set_no_show_all();
diagram.set_size_request(560, 165); diagram.signal_draw().connect(sigc::mem_fun(*this, &DisplaysPage::draw));
pack_start(diagram, false, false);
left.set_border_width(12); right.set_border_width(12);
@@ -126,7 +127,10 @@
body.pack_start(settings_tabs, true, true);
settings_scroll.add(body); settings_scroll.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
settings_scroll.set_min_content_height(120);
- pack_start(settings_scroll, true, true);
+ unavailable.set_line_wrap(); unavailable.set_max_width_chars(65);
+ settings_state.add(unavailable, "unavailable"); settings_state.add(settings_scroll, "settings");
+ settings_state.set_visible_child("unavailable");
+ pack_start(settings_state, true, true);
left.pack_start(combined, false, false);
general_grid.set_row_spacing(10); general_grid.set_column_spacing(12);
field(general_grid, 0, "Default desktop output", default_output);
@@ -151,14 +155,18 @@
role.append("desktop", "Desktop monitor"); role.append("masked", "Audio only — keep signal active"); role.append("off", "Disabled — signal off");
field(monitor_grid, 0, "Use", role); field(monitor_grid, 1, "Mode / refresh", mode);
position.set_placeholder_text("auto or x,y"); field(monitor_grid, 2, "Desktop position", position);
- scale.set_range(.25, 8); scale.set_increments(.25, 1); scale.set_digits(2); field(monitor_grid, 3, "Scale", scale);
+ scale.set_range(.25, 8); scale.set_increments(.25, 1); scale.set_digits(2); scale.set_value(1.0);
+ scale.get_accessible()->set_name("Physical monitor scale"); field(monitor_grid, 3, "Scale", scale);
for (auto text : {"normal", "90", "180", "270", "flipped", "flipped-90", "flipped-180", "flipped-270"}) rotation.append(text, text);
field(monitor_grid, 4, "Rotation", rotation);
local_gap.set_range(-1, 1000); local_gap.set_increments(1, 5);
local_gap.get_accessible()->set_name("Physical monitor zone gap");
local_gap.set_tooltip_text("-1 inherits the shared monitor-zone gap; 0 removes the gap for this physical monitor.");
field(monitor_grid, 5, "Zone gap (−1 = inherit)", local_gap);
- right.pack_start(monitor_grid, false, false); right.pack_start(include, false, false);
+ right.pack_start(monitor_grid, false, false);
+ scale_note.set_text("Scale 1.00 = 100%. Monitors combined into VIRTUAL-1 currently require 1.00.");
+ scale_note.set_line_wrap(); scale_note.set_max_width_chars(55); scale_note.set_halign(Gtk::ALIGN_START);
+ right.pack_start(scale_note, false, false); right.pack_start(include, false, false);
order_buttons.pack_start(left_button, true, true); order_buttons.pack_start(right_button, true, true);
right.pack_start(order_buttons, false, false);
status.set_line_wrap(); status.set_max_width_chars(65); status.set_halign(Gtk::ALIGN_START); status.set_selectable(true); pack_start(status, false, false);
@@ -230,13 +238,16 @@
throw std::runtime_error("WCM is editing a different configuration from the running compositor. Open its session configuration: " + data["config_file"].as_string());
if (data["pending"].as_bool() && transaction.empty())
{
- body.set_sensitive(false); apply_button.set_sensitive(false);
+ body.set_sensitive(false); apply_button.set_sensitive(false); identify_button.set_sensitive(false);
status.set_text("A display preview is awaiting confirmation in another window."); return;
}
+ bool recovering = !available;
if (discard || revision != data["revision"].as_string()) load(data);
- else update_controls();
+ available = true; update_controls();
+ if (recovering && !dirty) status.set_text("Changes are previewed for 20 seconds. Keep Changes saves them; closing WCM lets the preview revert.");
} catch (const std::exception& e)
{
+ loading = false; available = false; update_controls();
error(std::string(e.what()) + "\nDisplays needs the output-control and ipc plugins from the matching Wayfire package.");
apply_button.set_sensitive(false);
}
@@ -244,7 +255,7 @@
void DisplaysPage::load(const wf::json_t& data)
{
- loading = true; state = data; revision = data["revision"].as_string();
+ loading = true; revision.clear(); state = data;
original.clear(); draft.clear(); heads.clear(); order.clear(); monitors.remove_all();
wf::json_t opts = data["options"];
for (auto& key : opts.get_member_names()) original[key] = opts[key].as_string();
@@ -307,7 +318,8 @@
update_defaults();
if (!heads.count(selected)) selected = heads.empty() ? "" : heads.begin()->first;
monitors.set_active_id(selected);
- loading = false; select_monitor(); dirty = false; update_controls(); diagram.queue_draw();
+ loading = false; select_monitor(); dirty = false; revision = data["revision"].as_string();
+ update_controls(); diagram.queue_draw();
status.set_text("Changes are previewed for 20 seconds. Keep Changes saves them; closing WCM lets the preview revert.");
}
@@ -385,8 +397,11 @@
void DisplaysPage::update_controls()
{
bool preview = !transaction.empty();
- body.set_sensitive(!preview); refresh_button.set_sensitive(!preview); identify_button.set_sensitive(!heads.empty() && !preview);
- keep_button.set_visible(preview); revert_button.set_visible(preview); apply_button.set_visible(!preview); apply_button.set_sensitive(dirty && !preview);
+ settings_state.set_visible_child(available ? "settings" : "unavailable");
+ diagram.set_visible(available);
+ body.set_sensitive(available && !preview); refresh_button.set_sensitive(!preview);
+ identify_button.set_sensitive(available && !heads.empty() && !preview);
+ keep_button.set_visible(preview); revert_button.set_visible(preview); apply_button.set_visible(!preview); apply_button.set_sensitive(available && dirty && !preview);
bool desktop = role.get_active_id() == "desktop";
include.set_sensitive(desktop);
local_gap.set_sensitive(desktop && include.get_active());
--- a/src/displays.hpp
+++ b/src/displays.hpp
@@ -19,6 +19,8 @@
Gtk::Box left{Gtk::ORIENTATION_VERTICAL, 8}, right{Gtk::ORIENTATION_VERTICAL, 8};
Gtk::Notebook settings_tabs;
Gtk::ScrolledWindow settings_scroll;
+ Gtk::Stack settings_state;
+ Gtk::Label unavailable{"Display settings are unavailable. Check the message below, then Refresh."}, scale_note;
Gtk::Box actions{Gtk::ORIENTATION_HORIZONTAL, 8}, order_buttons{Gtk::ORIENTATION_HORIZONTAL, 8};
Gtk::Button refresh_button{"Refresh"}, identify_button{"Identify"}, apply_button{"Apply"};
Gtk::Button keep_button{"Keep Changes"}, revert_button{"Revert"}, left_button{"Move Left"}, right_button{"Move Right"};
@@ -45,7 +47,7 @@
std::map<std::string, std::string> original, draft;
wf::json_t state;
std::string revision, transaction, selected, config_file;
- bool loading = false, dirty = false;
+ bool loading = false, dirty = false, available = false;
int countdown = 0;
sigc::connection timer, identify_timer;
std::vector<std::unique_ptr<Gtk::Window>> identifiers;
|