Compare commits

..

No commits in common. "f311779ed95f43f1fdebed0f710ad84057e6fe19" and "d023bd7f58a54da08c3aad3c234a629b8a010892" have entirely different histories.

5 changed files with 17 additions and 74 deletions

View File

@ -1,15 +0,0 @@
# Exclude Dockerfile and .dockerignore so that the docker layer cache won't be
# invalidated after editing them (which changes the build context if they are
# not ignored).
*Dockerfile*
.dockerignore
# Exclude git metadata since we only care about the working tree.
.git
.gitattributes
.gitignore
# Exclude docs
*.md
*~
*.o
xkblayout-state

View File

@ -1,13 +0,0 @@
FROM alpine:3.14.2 AS build
RUN apk add --no-cache g++ libx11-dev make
WORKDIR /repo
COPY . .
RUN make
# RUN make && chmod a+x ./xkblayout-state
# Export to a minimal runtime image and run as an unprivileged user.
FROM alpine:3.14.2
RUN apk add --no-cache libstdc++ libx11
USER 1000:1000
WORKDIR /repo
COPY --from=build --chown=1000:1000 /repo/xkblayout-state .
ENTRYPOINT ["./xkblayout-state"]

View File

@ -13,7 +13,7 @@ $(objects): %.o: %.cpp $(headers)
$(CXX) $(CXXFLAGS) -Wall -c -o $@ $< $(CXX) $(CXXFLAGS) -Wall -c -o $@ $<
$(program): $(objects) $(program): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ -lX11 $(CXX) $(CXXFLAGS) -lX11 $(LDFLAGS) -o $@ $^
clean: clean:
rm -f $(program) $(objects) rm -f $(program) $(objects)

View File

@ -13,11 +13,9 @@ It's a thin wrapper around a slightly version of Jay Bromley's XKeyboard class,
Compilation and installation Compilation and installation
---------------------------- ----------------------------
- Make sure x11 development libraries are installed (eg. `apt install libx11-dev` on Ubuntu)
- To compile just say: `make` - To compile just say: `make`
- To install copy the resulting executable `xkblayout-state` somewhere in your path - To install copy the resulting executable `xkblayout-state` somewhere in your path
Alternatively with docker: `docker build .`
Usage Usage
----- -----

View File

@ -36,7 +36,6 @@ XKeyboard::XKeyboard()
int reasonReturn; int reasonReturn;
_display = XkbOpenDisplay(displayName, &eventCode, &errorReturn, &major, _display = XkbOpenDisplay(displayName, &eventCode, &errorReturn, &major,
&minor, &reasonReturn); &minor, &reasonReturn);
free(displayName);
switch (reasonReturn) { switch (reasonReturn) {
case XkbOD_BadLibraryVersion: case XkbOD_BadLibraryVersion:
throw X11Exception("Bad XKB library version."); throw X11Exception("Bad XKB library version.");
@ -92,10 +91,6 @@ Bool XKeyboard::initializeXkb()
if (kbdDescPtr->names == NULL) { if (kbdDescPtr->names == NULL) {
std::cerr << "Failed to get keyboard description." << std::endl; std::cerr << "Failed to get keyboard description." << std::endl;
XFree(kbdDescPtr);
XkbFreeControls(kbdDescPtr, XkbAllControlsMask, true);
XkbFreeNames(kbdDescPtr, XkbSymbolsNameMask, true);
XkbFreeNames(kbdDescPtr, XkbGroupNamesMask, true);
return False; return False;
} }
@ -127,7 +122,6 @@ Bool XKeyboard::initializeXkb()
_groupNames.push_back(""); _groupNames.push_back("");
} else { } else {
groupName = groupNameC; groupName = groupNameC;
// Remove everything after a brace, e.g. "English(US)" -> "English"
std::string::size_type pos = groupName.find('(', 0); std::string::size_type pos = groupName.find('(', 0);
if (pos != std::string::npos) { if (pos != std::string::npos) {
groupName = groupName.substr(0, pos - 1); groupName = groupName.substr(0, pos - 1);
@ -146,49 +140,32 @@ Bool XKeyboard::initializeXkb()
symName = symNameC; symName = symNameC;
XFree(symNameC); XFree(symNameC);
if (symName.empty()) { if (symName.empty()) {
XFree(kbdDescPtr);
XkbFreeControls(kbdDescPtr, XkbAllControlsMask, true);
XkbFreeNames(kbdDescPtr, XkbSymbolsNameMask, true);
XkbFreeNames(kbdDescPtr, XkbGroupNamesMask, true);
return False; return False;
} }
} else { } else {
XFree(kbdDescPtr);
XkbFreeControls(kbdDescPtr, XkbAllControlsMask, true);
XkbFreeNames(kbdDescPtr, XkbSymbolsNameMask, true);
XkbFreeNames(kbdDescPtr, XkbGroupNamesMask, true);
return False; return False;
} }
XkbSymbolParser symParser; XkbSymbolParser symParser;
// Parser is supposed to extract layout symbols (like us, de, ru)
// and variants (like dvorak) from symName string. But sometimes
// it gets nothing, for example on my system with Xwayland symName
// is "(unnamed)" and both _symbolNames and _variantNames are empty.
symParser.parse(symName, _symbolNames, _variantNames); symParser.parse(symName, _symbolNames, _variantNames);
int symNameCount = _symbolNames.size(); int count = _symbolNames.size();
if (count == 1 && _groupNames[0].empty() && _symbolNames[0] == "jp") {
if (symNameCount == 1 && _groupNames[0].empty() && _symbolNames[0] == "jp") {
_groupCount = 2; _groupCount = 2;
_symbolNames.resize(_groupCount);
_groupNames.resize(_groupCount);
_symbolNames[1] = _symbolNames[0]; _symbolNames[1] = _symbolNames[0];
_symbolNames[0] = "us"; _symbolNames[0] = "us";
_groupNames[0] = "US/ASCII"; _groupNames[0] = "US/ASCII";
_groupNames[1] = "Japanese"; _groupNames[1] = "Japanese";
} else { } else {
// If there are less symbol names, than groups, if (count < _groupCount) {
// fill remaining with default name of "en_US". int j = count;
if (symNameCount < _groupCount) { int k = _groupCount;
while (_symbolNames.size() < (size_t)_groupCount) { while (--j >= 0) _symbolNames[--k] = _symbolNames[j];
_symbolNames.insert(_symbolNames.begin(), "en_US"); while (--k >= 0) _symbolNames[k] = "en_US";
}
} }
} }
int groupNameCount = _groupNames.size(); count = _groupNames.size();
for (int i = 0; i < groupNameCount; i++) { for (int i = 0; i < count; i++) {
if (_groupNames[i].empty()) { if (_groupNames[i].empty()) {
std::string name = getSymbolNameByResNum(i); std::string name = getSymbolNameByResNum(i);
if (name.empty()) { if (name.empty()) {
@ -203,22 +180,18 @@ Bool XKeyboard::initializeXkb()
XkbStateRec xkbState; XkbStateRec xkbState;
XkbGetState(_display, _deviceId, &xkbState); XkbGetState(_display, _deviceId, &xkbState);
_currentGroupNum = xkbState.group; _currentGroupNum = xkbState.group;
XFree(kbdDescPtr);
XkbFreeControls(kbdDescPtr, XkbAllControlsMask, true);
XkbFreeNames(kbdDescPtr, XkbSymbolsNameMask, true);
XkbFreeNames(kbdDescPtr, XkbGroupNamesMask, true);
return True; return True;
} }
std::string XKeyboard::getSymbolNameByResNum(int groupResNum) std::string XKeyboard::getSymbolNameByResNum(int groupResNum)
{ {
return _symbolNames.at(groupNumResToXkb(groupResNum)); return _symbolNames[groupNumResToXkb(groupResNum)];
} }
std::string XKeyboard::getGroupNameByResNum(int groupResNum) std::string XKeyboard::getGroupNameByResNum(int groupResNum)
{ {
return _groupNames.at(groupNumResToXkb(groupResNum)); return _groupNames[groupNumResToXkb(groupResNum)];
} }
int XKeyboard::groupNumResToXkb(int groupResNum) int XKeyboard::groupNumResToXkb(int groupResNum)
@ -228,13 +201,13 @@ int XKeyboard::groupNumResToXkb(int groupResNum)
int XKeyboard::groupLookup(int srcValue, StringVector fromText, StringVector toText, int count) int XKeyboard::groupLookup(int srcValue, StringVector fromText, StringVector toText, int count)
{ {
const std::string srcText = fromText.at(srcValue); const std::string srcText = fromText[srcValue];
if (!srcText.empty()) { if (!srcText.empty()) {
std::string targetText; std::string targetText;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
targetText = toText.at(i); targetText = toText[i];
if (compareNoCase(srcText, targetText) == 0) { if (compareNoCase(srcText, targetText) == 0) {
srcValue = i; srcValue = i;
break; break;
@ -288,17 +261,17 @@ int XKeyboard::currentGroupNum() const
std::string XKeyboard::currentGroupName() const std::string XKeyboard::currentGroupName() const
{ {
return _groupNames.at(currentGroupNum()); return _groupNames[currentGroupNum()];
} }
std::string XKeyboard::currentGroupSymbol() const std::string XKeyboard::currentGroupSymbol() const
{ {
return _symbolNames.at(currentGroupNum()); return _symbolNames[currentGroupNum()];
} }
std::string XKeyboard::currentGroupVariant() const std::string XKeyboard::currentGroupVariant() const
{ {
return _variantNames.at(currentGroupNum()); return _variantNames[currentGroupNum()];
} }
bool XKeyboard::setGroupByNum(int groupNum) bool XKeyboard::setGroupByNum(int groupNum)