Add modem/networks DWM plugins, Dual-SIM & PIN/PUK support, built-in dmenu views, and game UX fixes
This commit is contained in:
+76
-7
@@ -42,7 +42,7 @@ constexpr int kWinX = 0;
|
||||
constexpr int kWinY = kTopBarHeight;
|
||||
constexpr int kWinWidth = kScreenWidth;
|
||||
constexpr int kWinHeight = kScreenHeight - kTopBarHeight; // 296px flush below 24px dwm bar
|
||||
constexpr int kRowCount = 7;
|
||||
constexpr int kRowCount = 8;
|
||||
|
||||
// Nerd Font PUA icons matching sxmo_hook_icons.sh & dwm ("Fira Code, DejaVuSansM Nerd Font")
|
||||
constexpr const char* kIconSpeaker = "\xef\x80\xa8"; // U+F028 speaker
|
||||
@@ -54,6 +54,8 @@ constexpr const char* kIconMicOn = "\xf3\xb0\x8d\xac"; // U+F036C mic on
|
||||
constexpr const char* kIconMicOff = "\xf3\xb0\x8d\xad"; // U+F036D mic off
|
||||
constexpr const char* kIconBrightness = "\xf3\xb0\x83\x9d"; // U+F00DD brightness
|
||||
constexpr const char* kIconKeyboard = "\xef\x84\x9c"; // U+F11C keyboard
|
||||
constexpr const char* kIconBell = "\xef\x83\xb3"; // U+F0F3 bell / ringer
|
||||
constexpr const char* kIconBellSlash = "\xef\x87\xb6"; // U+F1F6 bell-slash
|
||||
constexpr const char* kIconToggleOn = "\xef\x88\x85"; // U+F205 toggle on
|
||||
constexpr const char* kIconToggleOff = "\xef\x88\x84"; // U+F204 toggle off
|
||||
|
||||
@@ -240,8 +242,9 @@ enum class ControlId {
|
||||
Flashlight = 2,
|
||||
SoundMute = 3,
|
||||
MicMute = 4,
|
||||
ScreenBright = 5,
|
||||
KbdBright = 6,
|
||||
RingerMode = 5,
|
||||
ScreenBright = 6,
|
||||
KbdBright = 7,
|
||||
};
|
||||
|
||||
struct ControlItem {
|
||||
@@ -314,7 +317,12 @@ class PhoneController {
|
||||
items_.push_back({ControlId::MicMute, kIconMicOn, kIconMicOff,
|
||||
"Microphone", false, 0, 1, 1, (dec1 > 0) ? 1 : 0});
|
||||
|
||||
// 6. Screen brightness (slider 1..screenMax_)
|
||||
// 6. Ringer Mode (0=Ring+Vib, 1=Vibrate, 2=Silent, 3=DND)
|
||||
int ringerVal = readRingerMode();
|
||||
items_.push_back({ControlId::RingerMode, kIconBell, kIconBellSlash,
|
||||
"Ringer", false, 0, 3, 1, ringerVal});
|
||||
|
||||
// 7. Screen brightness (slider 1..screenMax_)
|
||||
int scrCur = std::clamp(readIntFile(backlightDir_ + "/brightness", screenMax_), 1, screenMax_);
|
||||
int scrStep = std::max(1, screenMax_ / 14);
|
||||
items_.push_back({ControlId::ScreenBright, kIconBrightness, kIconBrightness,
|
||||
@@ -342,6 +350,8 @@ class PhoneController {
|
||||
ControlItem& it = items_[idx];
|
||||
if (it.isSlider) {
|
||||
it.value = std::clamp(it.value + dir * it.stepVal, it.minVal, it.maxVal);
|
||||
} else if (it.id == ControlId::RingerMode) {
|
||||
it.value = (it.value + dir + 4) % 4;
|
||||
} else {
|
||||
it.value = it.value ? 0 : 1;
|
||||
}
|
||||
@@ -353,13 +363,38 @@ class PhoneController {
|
||||
return;
|
||||
}
|
||||
ControlItem& it = items_[idx];
|
||||
if (!it.isSlider) {
|
||||
if (it.id == ControlId::RingerMode) {
|
||||
it.value = (it.value + 1) % 4;
|
||||
apply(it);
|
||||
} else if (!it.isSlider) {
|
||||
it.value = it.value ? 0 : 1;
|
||||
apply(it);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string getSxmoCfgDir() {
|
||||
const char* xdg = std::getenv("XDG_CONFIG_HOME");
|
||||
if (xdg && xdg[0]) {
|
||||
return std::string(xdg) + "/sxmo";
|
||||
}
|
||||
const char* home = std::getenv("HOME");
|
||||
return std::string((home && home[0]) ? home : "/home/user") + "/.config/sxmo";
|
||||
}
|
||||
|
||||
static int readRingerMode() {
|
||||
std::string busyFile = getRuntimeFile("sxmo.busy");
|
||||
if (::access(busyFile.c_str(), F_OK) == 0) {
|
||||
return 3; // DND
|
||||
}
|
||||
std::string cfg = getSxmoCfgDir();
|
||||
bool noRing = (::access((cfg + "/.noring").c_str(), F_OK) == 0);
|
||||
bool noVib = (::access((cfg + "/.novibrate").c_str(), F_OK) == 0);
|
||||
if (noRing && noVib) return 2; // Silent
|
||||
if (noRing) return 1; // Vibrate only
|
||||
return 0; // Ring + Vibrate
|
||||
}
|
||||
|
||||
void apply(ControlItem& it) {
|
||||
switch (it.id) {
|
||||
case ControlId::SpeakerVol: {
|
||||
@@ -404,6 +439,30 @@ class PhoneController {
|
||||
: "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ 1 >/dev/null 2>&1");
|
||||
break;
|
||||
}
|
||||
case ControlId::RingerMode: {
|
||||
std::string cfg = getSxmoCfgDir();
|
||||
::mkdir(cfg.c_str(), 0755);
|
||||
std::string noRingPath = cfg + "/.noring";
|
||||
std::string noVibPath = cfg + "/.novibrate";
|
||||
std::string busyPath = getRuntimeFile("sxmo.busy");
|
||||
if (it.value == 0) { // Ring + Vibrate
|
||||
::unlink(noRingPath.c_str());
|
||||
::unlink(noVibPath.c_str());
|
||||
::unlink(busyPath.c_str());
|
||||
} else if (it.value == 1) { // Vibrate only
|
||||
writeIntFile(noRingPath, 1);
|
||||
::unlink(noVibPath.c_str());
|
||||
::unlink(busyPath.c_str());
|
||||
} else if (it.value == 2) { // Silent
|
||||
writeIntFile(noRingPath, 1);
|
||||
writeIntFile(noVibPath, 1);
|
||||
::unlink(busyPath.c_str());
|
||||
} else { // DND
|
||||
writeIntFile(busyPath, 1);
|
||||
}
|
||||
runAsyncCmd("sxmo_hook_statusbar.sh audio >/dev/null 2>&1");
|
||||
break;
|
||||
}
|
||||
case ControlId::ScreenBright: {
|
||||
writeIntFile(backlightDir_ + "/bl_power", 0);
|
||||
writeIntFile(backlightDir_ + "/brightness", it.value);
|
||||
@@ -597,10 +656,11 @@ static int xdrawer_run_main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
const ControlItem& it = items[i];
|
||||
bool activeState = (it.value > 0);
|
||||
bool activeState = (it.id == ControlId::RingerMode) ? (it.value == 0 || it.value == 1)
|
||||
: (it.value > 0);
|
||||
const char* rowIcon = activeState ? it.iconOn : it.iconOff;
|
||||
|
||||
int labelMaxW = it.isSlider ? 82 : 136;
|
||||
int labelMaxW = it.isSlider ? 82 : 126;
|
||||
drawPango(layoutIcon, isSel ? &colYellow : &colLight, 8, ry, rowH, rowIcon);
|
||||
drawPango(layoutMain, isSel ? &colWhite : &colLight, 30, ry, rowH,
|
||||
it.label, labelMaxW);
|
||||
@@ -643,6 +703,13 @@ static int xdrawer_run_main(int argc, char** argv) {
|
||||
int pw = pangoWidth(layoutSmall, pctStr);
|
||||
drawPango(layoutSmall, isSel ? &colWhite : &colLight, kWinWidth - pw - 6,
|
||||
ry, rowH, pctStr);
|
||||
} else if (it.id == ControlId::RingerMode) {
|
||||
const char* rModes[4] = {"Ring+Vib", "Vibrate", "Silent", "DND"};
|
||||
std::string stStr = std::string("< ") + rModes[std::clamp(it.value, 0, 3)] + " >";
|
||||
int stW = pangoWidth(layoutSmall, stStr);
|
||||
XftColor* rCol = (it.value == 0) ? (isSel ? &colYellow : &colGreen)
|
||||
: ((it.value == 1) ? &colYellow : &colMuted);
|
||||
drawPango(layoutSmall, rCol, kWinWidth - stW - 6, ry, rowH, stStr);
|
||||
} else {
|
||||
bool on = (it.value != 0);
|
||||
std::string stStr = on ? "ON" : "OFF";
|
||||
@@ -715,6 +782,8 @@ static int xdrawer_run_main(int argc, char** argv) {
|
||||
closeOtherPlugin("xfiles.pid", "/tmp/dwm_plugin_files.fifo");
|
||||
closeOtherPlugin("xcamera.pid", "/tmp/dwm_plugin_camera.fifo");
|
||||
closeOtherPlugin("xthemes.pid", "/tmp/dwm_plugin_themes.fifo");
|
||||
closeOtherPlugin("xmodem.pid", "/tmp/dwm_plugin_modem.fifo");
|
||||
closeOtherPlugin("xnetworks.pid", "/tmp/dwm_plugin_networks.fifo");
|
||||
theme.checkAndReload(dpy, screen, visual, cmap, layoutMain, layoutSmall,
|
||||
layoutIcon, nullptr, win);
|
||||
openStartMs = nowMs();
|
||||
|
||||
Reference in New Issue
Block a user