Page 1 of 1

Flag near the cursor in Linux (?)

Posted: Fri Dec 15, 2023 8:34 pm
by AZJIO
Is it possible to write such a program on Linux?
Download (cursors included)
Several times I came across the file "KlavaState_Cursor.pb" and I modified it a little.
One person gave me a link to this file and asked if it could be compiled for Linux. I said no, because it uses WinAPI. But I googled GTK3 functions and found gdk_cursor_new_from_pixbuf_(). But the presence of this function can only solve half of the problem; I also need to catch the layout switching event.

Code: Select all

EnableExplicit

#EnCode = $4090409
#RuCode = $4190419 ; set your native language...  задайте свой родной язык
; https://www.autoitscript.com/autoit3/docs/appendix/OSLangCodes.htm
; $40c040c
; $4070407
#EnStr$ = "En"
#RuStr$ = "Ru" ; it will be written on the tray icon ...   это будет написано на иконке в трее
; "Fr"
; "De"

#Window = 0
#SysTrayIcon = 0
#mClose = 0
#Timer = 0
#Menu = 0
#Font0 = 0
#Lang0 = 0
#Lang1 = 1

Global hRuCur, hEnCur, hDefault, hFont, hRuCurCopy, hEnCurCopy

; Structure Lang
; 	Array aLang.i(0)
; EndStructure

; Global aLang.Lang
Define CountLang

CountLang = GetKeyboardLayoutList_(0, 0)
If CountLang < 2
; 	MessageRequester("Error", "Используется один язык, нет смысла в этой программе", #MB_OK | #MB_ICONERROR)
	MessageRequester("Error", "One language is used, there is no point in this program", #MB_OK | #MB_ICONERROR)
	End
EndIf
; Debug "Number of languages: " +  CountLang
; Debug "Число языков: " +  CountLang
; ReDim aLang\aLang(CountLang - 1)
; 
; GetKeyboardLayoutList_(CountLang, @aLang\aLang())

; ShowMemoryViewer(@aLang\aLang(), SizeOf(i) * 2)

; For i = 0 To ArraySize(aLang\aLang())
;     Debug aLang\aLang(i) >> 16
;     Debug aLang\aLang(i) & $FFF
; Next


hEnCur = LoadCursorFromFile_(@"En.cur")
hRuCur = LoadCursorFromFile_(@"Ru.cur")
hDefault = LoadCursorFromFile_(@"C:\Windows\Cursors\beam_m.cur")
If Not (hRuCur And hEnCur And hDefault)
; 	MessageRequester("Error", "Не удалось загрузить курсор", #MB_OK | #MB_ICONERROR)
	MessageRequester("Error", "Failed to load cursor!", #MB_OK | #MB_ICONERROR)
	End
EndIf


Procedure GetLayoutWindowActive()
	Protected Layout
	Static LayoutTemp
	Layout = GetKeyboardLayout_(GetWindowThreadProcessId_(GetForegroundWindow_(), 0))
	If LayoutTemp <> Layout
		LayoutTemp = Layout
		If Layout = #RuCode
			ChangeSysTrayIcon(#SysTrayIcon, ImageID(#Lang0))
			hRuCurCopy = CopyIcon_(hRuCur)
			; функция уничтожает курсор после его переопределения, поэтому мы не можем применить его дважды без копирования.
			SetSystemCursor_(hRuCurCopy, #OCR_IBEAM)
		ElseIf Layout = #EnCode
			ChangeSysTrayIcon(#SysTrayIcon, ImageID(#Lang1))
			hEnCurCopy = CopyIcon_(hEnCur)
			SetSystemCursor_(hEnCurCopy, #OCR_IBEAM)
		Else
			SetSystemCursor_(hDefault, #OCR_IBEAM)
		EndIf
; 		Debug GetLastError_() ; 1402 = ERROR_INVALID_CURSOR_HANDLE
; 		https://learn.microsoft.com/ru-ru/windows/win32/Debug/system-error-codes--1300-1699-
; 		Debug Hex(Layout)
	EndIf
EndProcedure

hFont = LoadFont(#Font0, "Tahoma", 9, #PB_Font_Bold | #PB_Font_HighQuality)


Procedure CreateIcon(id, Text$, ColorFR, ColorBG)
	If CreateImage(id, 16 , 16, 24, ColorBG) And StartDrawing(ImageOutput(id))
	; 	Box(0, 0, 16, 16, ColorBG)
		DrawingMode(#PB_2DDrawing_Transparent)
		DrawingFont(hFont)
		DrawText(0, 0, Text$, ColorFR)
		StopDrawing()
	EndIf
EndProcedure

; Рисуем иконки. В идеале получить буквы языков
CreateIcon(#Lang0, #RuStr$, $006600, $00FF00)
CreateIcon(#Lang1, #EnStr$, $000055, $0000FF)


;-┌───GUI───┐
If OpenWindow(#Window, 0, 0, 100, 20, "", #PB_Window_Invisible)

	AddSysTrayIcon(#SysTrayIcon, WindowID(#Window), ImageID(#Lang0))
; 	SysTrayIconToolTip(#SysTrayIcon, "Русский")
; 	SysTrayIconToolTip(#SysTrayIcon, "Russian")

	If CreatePopupMenu(#Menu)
; 		MenuItem(#mClose, "Закрыть")
		MenuItem(#mClose, "Close")
	EndIf

	SetTimer_(WindowID(#Window), #Timer, 200, @GetLayoutWindowActive())

;-┌───Loop───┐
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_SysTray
				If EventType() = #PB_EventType_RightClick
					DisplayPopupMenu(#Menu, WindowID(#Window) )
				EndIf
			Case #PB_Event_Menu
				If EventMenu() = #mClose
					Break
				EndIf
		EndSelect
	ForEver
;-└───Loop───┘
EndIf

KillTimer_(WindowID(#Window), #Timer)
CloseWindow(#Window)
SetSystemCursor_(hDefault, #OCR_IBEAM) ; возвращаем старый курсор, хотя это не возвращает ваш курсор.
DestroyCursor_(hEnCurCopy)
DestroyCursor_(hRuCurCopy)
DestroyCursor_(hRuCur)
DestroyCursor_(hEnCur)
; DestroyCursor_(hDefault)
End