Skip to content

Commit

Permalink
#1 Improve Linux support
Browse files Browse the repository at this point in the history
  • Loading branch information
siropkin committed Jul 27, 2023
1 parent 9165070 commit 27c7094
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 33 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@

## [Unreleased]


## [1.0.3] - 2023-07-28
### Changed
- Improve Linux support


## [1.0.2] - 2023-07-27
### Changed
- Update `pluginUntilBuild` to include `232.*` (2023.2.*)


## [1.0.1] - 2023-07-13
### Added
- Added Linux support
### Changed
- Turning "Show default language" off by default


## [1.0.0] - 2023-06-16
### Added
- Initial release
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginGroup = com.github.siropkin.kursor
pluginName = Kursor
pluginRepositoryUrl = https://github.com/siropkin/kursor
# SemVer format -> https://semver.org
pluginVersion = 1.0.2
pluginVersion = 1.0.3

# Supported build number ranges and IntelliJ Platform versions -> https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
pluginSinceBuild = 221
Expand Down
106 changes: 75 additions & 31 deletions src/main/kotlin/com/github/siropkin/kursor/Kursor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import java.awt.event.ComponentEvent
import java.awt.event.ComponentListener
import java.awt.event.KeyEvent
import java.awt.im.InputContext
import java.io.BufferedReader
import java.io.*
import java.util.*
import javax.swing.JComponent

Expand All @@ -24,6 +24,8 @@ object Position {

class Kursor(private var editor: Editor): JComponent(), ComponentListener, CaretListener {
private val os = System.getProperty("os.name").lowercase()
private var linuxDistribution = System.getenv("DESKTOP_SESSION")?.lowercase() ?: ""
private var linuxKeyboardLayouts: List<String> = listOf()

init {
editor.contentComponent.add(this)
Expand Down Expand Up @@ -58,37 +60,79 @@ class Kursor(private var editor: Editor): JComponent(), ComponentListener, Caret
return KursorSettings.getInstance()
}

private fun getLanguage(): String {
var language: String? = null

if (os == "linux") {
// This is not the ideal solution because it involves executing a shell command to know the current keyboard layout which might affect the performance.
// But it is the only solution I found that works on Linux.
try {
val process = Runtime.getRuntime().exec("gsettings get org.gnome.desktop.input-sources mru-sources")
val output = process.inputStream.bufferedReader().use(BufferedReader::readText)
process.waitFor()
if (process.exitValue() == 0) {
language = output.substringAfter("('xkb', '").substringBefore("')").substring(0, 2)
// if the language is "us" then it is actually "en"
if (language == "us") {
language = "en"
}
}
} catch (e: Exception) {
e.printStackTrace()
}
} else {
val context: InputContext = InputContext.getInstance()
language = context.locale.toString().substring(0, 2)
private fun executeNativeCommand(command: String): String {
return try {
val process = Runtime.getRuntime().exec(command)
process.waitFor()
process.inputStream.bufferedReader().use(BufferedReader::readText)
} catch (e: IOException) {
e.printStackTrace()
""
}
}

private fun getUbuntuKeyboardLayout(): String {
val commandOutput = executeNativeCommand("gsettings get org.gnome.desktop.input-sources mru-sources")
return commandOutput
.substringAfter("('xkb', '")
.substringBefore("')")
.substring(0, 2)
}

return language ?: "un"
private fun getNonUbuntuKeyboardLayouts(): List<String> {
if (linuxKeyboardLayouts.isNotEmpty()) {
return linuxKeyboardLayouts
}
linuxKeyboardLayouts = executeNativeCommand("setxkbmap -query")
.substringAfter("layout:")
.substringBefore("\n")
.trim()
.split(",")
return linuxKeyboardLayouts
}

private fun getNonUbuntuKeyboardLayoutIndex(): Int {
return executeNativeCommand("xset -q")
.substringAfter("LED mask:")
.substringBefore("\n")
.trim()
.substring(4, 5)
.toInt(16)
}

private fun getNonUbuntuKeyboardLayout(): String {
val linuxKeyboardLayouts = getNonUbuntuKeyboardLayouts()
val linuxCurrentKeyboardLayoutIndex = getNonUbuntuKeyboardLayoutIndex()
return linuxKeyboardLayouts[linuxCurrentKeyboardLayoutIndex]
}

private fun getKeyboardLayout(): String {
// This is not the ideal solution because it involves executing a shell command to know the current keyboard layout
// which might affect the performance. And we have different commands for different Linux distributions.
// But it is the only solution I found that works on Linux.
var language = when (os) {
"linux" -> when (linuxDistribution) {
"ubuntu" -> getUbuntuKeyboardLayout()
else -> getNonUbuntuKeyboardLayout()
}
else -> InputContext.getInstance()
.locale
.toString()
.substring(0, 2)
}
if (language == "us") {
language = "en"
}
if (language.isEmpty()) {
language = getSettings().defaultLanguage
}
return language
}

private fun isCapsLockOn(): Boolean {
val toolkit = Toolkit.getDefaultToolkit()
return toolkit.getLockingKeyState(KeyEvent.VK_CAPS_LOCK)
return Toolkit
.getDefaultToolkit()
.getLockingKeyState(KeyEvent.VK_CAPS_LOCK)
}

private fun isOverwriteModeOn(): Boolean {
Expand Down Expand Up @@ -155,11 +199,11 @@ class Kursor(private var editor: Editor): JComponent(), ComponentListener, Caret
}

val settings = getSettings()
val language = getLanguage()
val keyboardLayout = getKeyboardLayout()
val isCapsLockOn = isCapsLockOn()

val caret = getPrimaryCaret()
val caretColor = if (settings.changeColorOnNonDefaultLanguage && language != settings.defaultLanguage) {
val caretColor = if (settings.changeColorOnNonDefaultLanguage && keyboardLayout != settings.defaultLanguage) {
settings.colorOnNonDefaultLanguage
} else {
null
Expand All @@ -168,12 +212,12 @@ class Kursor(private var editor: Editor): JComponent(), ComponentListener, Caret
setCaretColor(caret, caretColor)
}

val isIndicatorVisible = settings.showIndicator && (settings.indicateDefaultLanguage || language != settings.defaultLanguage || settings.indicateCapsLock && isCapsLockOn)
val isIndicatorVisible = settings.showIndicator && (settings.indicateDefaultLanguage || keyboardLayout != settings.defaultLanguage || settings.indicateCapsLock && isCapsLockOn)
if (!isIndicatorVisible) {
return
}

val indicatorText = if (settings.indicateCapsLock && isCapsLockOn) language.uppercase(Locale.getDefault()) else language
val indicatorText = if (settings.indicateCapsLock && isCapsLockOn) keyboardLayout.uppercase(Locale.getDefault()) else keyboardLayout

val caretWidth = getCaretWidth(caret)
val caretHeight = getCaretHeight(caret)
Expand Down
7 changes: 6 additions & 1 deletion src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<idea-plugin require-restart="true">
<id>com.github.siropkin.kursor</id>
<name>Kursor</name>
<version>1.0.2</version>
<version>1.0.3</version>
<vendor email="[email protected]">Ivan Seredkin</vendor>

<description><![CDATA[
Expand All @@ -11,6 +11,11 @@
]]></description>

<change-notes><![CDATA[
1.0.3 (2023-07-28)<br />
++++++++++++++++++<br />
- Improve Linux support<br />
<br />
<br />
1.0.2 (2023-07-27)<br />
++++++++++++++++++<br />
- Update `pluginUntilBuild` to include `232.*` (2023.2.*)<br />
Expand Down

0 comments on commit 27c7094

Please sign in to comment.