Kursor is an IntelliJ plugin that enhances productivity by dynamically displaying the current keyboard language on your cursor and changing its color based on the language. Ideal for multilingual developers, it aims to minimize typing errors.
I installed the plug-in, but couldn't find the relevant configuration.
My input method comes with English and Chinese, and I did not switch the input type through the system language. It seems that this situation cannot be detected by the plug-in.
I tested and found that the plug-in monitors the input method switching shortcut keys, not the actual language status.
Hello. Firtst of all, thank you for developing the great plugin.
This plugin makes me more productive. Thank you!
I used two languages, English and Korean.
Korean looks correct ko, but english is showing _U.
And Kursor plugin looks dose not recognize this _U with English, because Change color on non-default language worked on this _U.
I use macOS Sonoma 14.0 and if you need more some log file, then comment me.
Thank you.
It would be helpful to have a "Detect Keyboard Layout" button in the plugin settings. This button would detect the current keyboard layout and prefill it into the settings, making the configuration process smoother and more user-friendly.
Benefits:
Simplifies the setup process for users.
Ensures accurate detection of the current keyboard layout.
Reduces the risk of errors during manual configuration.
After switching Czech keyboard layout, the IDE rendering gets broken and more (check the footage), sometimes I also get the following error.
Footage
[Kooha-2024-04-27-21-28-52.webm](https://github.com/siropkin/kursor/assets/100159609/fea79c59-df42-4396-b344-2b47fbdd7ec4)
Stacktrace
```
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.base/java.util.Collections$SingletonList.get(Collections.java:4959)
at com.github.siropkin.kursor.Kursor.getLinuxNonUbuntuKeyboardLayout(Kursor.kt:106)
at com.github.siropkin.kursor.Kursor.getKeyboardLayout(Kursor.kt:126)
at com.github.siropkin.kursor.Kursor.paintComponent(Kursor.kt:209)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1115)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at com.intellij.openapi.editor.impl.EditorComponentImpl.paint(EditorComponentImpl.java:156)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JViewport.paint(JViewport.java:736)
at com.intellij.ui.components.JBViewport.paint(JBViewport.java:235)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JLayeredPane.paint(JLayeredPane.java:586)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintChildren(JComponent.java:955)
at com.intellij.openapi.fileEditor.impl.EditorTabs.paintChildren(EditorTabbedContainer.kt:607)
at java.desktop/javax.swing.JComponent.paint(JComponent.java:1124)
at java.desktop/javax.swing.JComponent.paintToOffscreen(JComponent.java:5312)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBufferedImpl(RepaintManager.java:1668)
at java.desktop/javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1643)
at java.desktop/javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1580)
at java.desktop/javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:272)
at java.desktop/javax.swing.RepaintManager.paint(RepaintManager.java:1347)
at java.desktop/javax.swing.JComponent._paintImmediately(JComponent.java:5260)
at java.desktop/javax.swing.JComponent.paintImmediately(JComponent.java:5070)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:882)
at java.desktop/javax.swing.RepaintManager$4.run(RepaintManager.java:865)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:865)
at java.desktop/javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:838)
at java.desktop/javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:787)
at java.desktop/javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1909)
at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:792)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:761)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:698)
at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$12(IdeEventQueue.kt:593)
at com.intellij.openapi.application.impl.RwLockHolder.runWithoutImplicitRead(RwLockHolder.kt:105)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:593)
at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:77)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:362)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:361)
at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:843)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:361)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:356)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1021)
at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:114)
at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1021)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:356)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:393)
at com.intellij.ide.IdeEventQueue.pumpEventsForHierarchy(IdeEventQueue.kt:734)
at com.intellij.openapi.progress.util.ProgressWindow.lambda$startBlocking$4(ProgressWindow.java:231)
at com.intellij.openapi.application.impl.RwLockHolder.runUnlockingIntendedWrite(RwLockHolder.kt:223)
at com.intellij.openapi.application.impl.ApplicationImpl.runUnlockingIntendedWrite(ApplicationImpl.java:835)
at com.intellij.openapi.progress.util.ProgressWindow.lambda$startBlocking$5(ProgressWindow.java:226)
at com.intellij.openapi.progress.util.ProgressWindow.executeInModalContext(ProgressWindow.java:207)
at com.intellij.openapi.progress.util.ProgressWindow.startBlocking(ProgressWindow.java:224)
at com.intellij.openapi.progress.impl.ProgressRunner.lambda$execFromEDT$7(ProgressRunner.java:316)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
at com.intellij.openapi.progress.impl.ProgressRunner.execFromEDT(ProgressRunner.java:313)
at com.intellij.openapi.progress.impl.ProgressRunner.submit(ProgressRunner.java:253)
at com.intellij.openapi.progress.impl.ProgressRunner.submitAndGet(ProgressRunner.java:194)
at com.intellij.openapi.application.impl.ApplicationImpl.runProcessWithProgressSynchronously(ApplicationImpl.java:385)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:578)
at com.intellij.openapi.progress.impl.ProgressManagerImpl.runProcessWithProgressSynchronously(ProgressManagerImpl.java:104)
at com.intellij.openapi.progress.impl.CoreProgressManager.runProcessWithProgressSynchronously(CoreProgressManager.java:295)
at com.intellij.codeInsight.editorActions.SelectWordHandler.selectWord(SelectWordHandler.java:96)
at com.intellij.codeInsight.editorActions.SelectWordHandler.doExecute(SelectWordHandler.java:61)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:202)
at com.intellij.openapi.editor.actions.SelectWordAtCaretAction$Handler.doExecute(SelectWordAtCaretAction.java:92)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:202)
at com.jetbrains.rdserver.actions.BackendSelectWordAtCaretHandler.doExecute(BackendSelectWordAtCaretHandler.kt:18)
at com.intellij.openapi.editor.actionSystem.DynamicEditorActionHandler.doExecute(DynamicEditorActionHandler.java:63)
at com.intellij.openapi.editor.actionSystem.EditorActionHandler.execute(EditorActionHandler.java:202)
at com.intellij.openapi.editor.impl.CaretImpl.lambda$selectWordAtCaret$9(CaretImpl.java:1302)
at com.intellij.openapi.editor.impl.CaretModelImpl.doWithCaretMerging(CaretModelImpl.java:412)
at com.intellij.openapi.editor.impl.CaretImpl.selectWordAtCaret(CaretImpl.java:1287)
at com.intellij.openapi.editor.impl.EditorImpl.selectWordAtCaret(EditorImpl.java:4549)
at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.processMousePressed(EditorImpl.java:4455)
at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.lambda$runMousePressedCommand$0(EditorImpl.java:4178)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:225)
at com.intellij.openapi.command.impl.CoreCommandProcessor.executeCommand(CoreCommandProcessor.java:177)
at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.runMousePressedCommand(EditorImpl.java:4183)
at com.intellij.openapi.editor.impl.EditorImpl$MyMouseAdapter.mousePressed(EditorImpl.java:4100)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6654)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3385)
at java.desktop/java.awt.Component.processEvent(Component.java:6422)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:5027)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4969)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4580)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4524)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2809)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4855)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:794)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:739)
at java.desktop/java.awt.EventQueue$3.run(EventQueue.java:733)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:766)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:764)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:763)
at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:698)
at com.intellij.ide.IdeEventQueue.dispatchMouseEvent(IdeEventQueue.kt:637)
at com.intellij.ide.IdeEventQueue._dispatchEvent$lambda$10(IdeEventQueue.kt:584)
at com.intellij.openapi.application.impl.RwLockHolder.runWithEnabledImplicitRead(RwLockHolder.kt:138)
at com.intellij.openapi.application.impl.RwLockHolder.runWithImplicitRead(RwLockHolder.kt:129)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:584)
at com.intellij.ide.IdeEventQueue.access$_dispatchEvent(IdeEventQueue.kt:77)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:362)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1$1.compute(IdeEventQueue.kt:361)
at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:843)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:361)
at com.intellij.ide.IdeEventQueue$dispatchEvent$processEventRunnable$1$1.invoke(IdeEventQueue.kt:356)
at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$1(IdeEventQueue.kt:1021)
at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:114)
at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1021)
at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$7(IdeEventQueue.kt:356)
at com.intellij.openapi.application.impl.RwLockHolder.runIntendedWriteActionOnCurrentThread(RwLockHolder.kt:209)
at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:830)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:398)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
```
The problem seems to be with the usage of setxkbmap as it will warn you when using it on Wayland and won't return the correct input method either. Also, just a little warning for you, there's no need to use GNOME on Ubuntu either, so the gsettings command could fail too.
Not all host operating systems provide API to determine the locale of the currently selected native input method or keyboard layout, and to select a native input method or keyboard layout by locale. For host operating systems that don't provide such API, selectInputMethod assumes that native input methods or keyboard layouts provided by the host operating system support only the system's default locale.
My system details
Ubuntu 22.10, Gnome
IntelliJ IDEA 2023.1.3 (Ultimate Edition)
Runtime version: 17.0.7+10-b829.16 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
I would like the option to show keyboard layouts on cursor.
I have the same language but use different layouts, which makes the Kursor language info somewhat irrelevant.
Would be awesome if there was an option to have the cursor info instead show the layout instead of language.
So in my case it would say SV and US, or similar, instead of EN for both.
A bonus would be if there was a “default layout” and “show default layout” option as well.
For this, I think can make a configuration, read the input method currently enabled on the system in the settings, and then make a mapping, so that don't have to worry about what to display.
The idea comes from that comment ^ - add the ability to map different input methods and their display labels.
For example, on the plugin settings form there will be the ability to add display label mapping to any detected language: