Focus auf eigenes Fenster setzen

In dieser Linux-Ecke dürfen nur Themen rund um Linux geschrieben werden.
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
jogo
Beiträge: 64
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint Mate

Re: Focus auf eigenes Fenster setzen

Beitrag von jogo »

Hi Jürgen,
jetzt hast du ins Schwarze getroffen! Dein Beispielcode ist super und funktioniert einwandfrei. Vielen Dank.
Bin grad dabei, ihn zu verstehen um ihn in mein Projekt einzubauen.
Dann hab ich jetzt 2 Schnipsel von dir, aus denen man viel herleiten und anwenden kann - immer wieder hilfreich.

Da ist mir doch glatt schon die Idee gekommen, daß ich ja unter bestimmten Bedingungen dann den Focus wieder auf das zuletzt benutzte Fenster zurückgeben könnte, wenn ich in meinen Programm alles erledigt habe.
Ich müßte ja dann, bevor ich mir den Focus hole, die Fenster-ID des Fensters ermitteln & merken, welches grad den Fokus hat.

Aber ok, ich bau erstmal deine Lösung ein, um mir den Focus zu holen :-)
--
Ideen gibt es viele - man muss sie nur haben...
Mint 18.3/19.3/21.x/LMDE5 // PureBasic 5.73 / 6.02
Num500
Beiträge: 19
Registriert: 23.12.2004 18:50
Wohnort: Buchholz

Re: Focus auf eigenes Fenster setzen

Beitrag von Num500 »

Hallo jogo,

schön das Du was damit anfangen kannst.
In diesem Fall verwende ich als Deine Bestimmung den Timer alle 10 Sekunden (umschaltbar per Button auf Thread-Bedingung),
das Programm setzt den Focus auf sich selbst (per wmctrl), druck ESC-Taste wird angezeigt.
Bei Programmstart ist Sticky eingeschaltet (umschaltbar per Button).
Habe es noch erweitert um das Fenster mit dem Focus zuvor zu ermitteln, per 'xdotool' was vorhanden sein muß.
Nach der ersten Bedingung kann per Button 'zum letzten Focus' wieder zum vorherigen Fenster gewechselt werden.

Code: Alles auswählen

; Programm: Testprogramm OnTop für Linux, Focus auf sich selbst und zurück zum Fenster mit vorherigem Focus
; Datum:       15.11.2021
; Purebasic:    5.73 LTS  (Linux 64bit)
;
;Verweis:   http://forums.purebasic.com/german/viewtopic.php?f=21&t=32529&sid=2dd30ce33b8e458c473a777e96d0dc08
;
EnableExplicit

Global Fenster.s = "OnTop-Focus-Return Test"    ;hier den entsprechenden Fenstertitel eintragen
Global ZustandStickyAktiv = #True
Global BedingungTimer = #True
Global ThreadNrTEST = 0
Global FlagThreadBeenden = #False
Global FensterLetzterFocus.s =""

Enumeration FormWindow
  #Window_Main
EndEnumeration

Enumeration FormGadget
  #ButtonSticky
  #ButtonBedingung
  #ButtonLetzterFocus
  #TextGadget1
  #TextGadget2
  #TextGadget3
  #TextGadget4
EndEnumeration

Enumeration
  #TimerNummerOnTop
EndEnumeration
;
Procedure FensterOnTop(gWinTitle.s)
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Protected.i gProgrammId
    gProgrammId = RunProgram("wmctrl", "-a " + #DQUOTE$ + gWinTitle + #DQUOTE$, "", #PB_Program_Hide)
    If  gProgrammId = 0
      MessageRequester("Linux wmctrl", "wmctrl fehlt, bitte installieren z.B.: apt install wmctrl")
    EndIf
  CompilerEndIf
EndProcedure
;
Procedure.s WerHatDenFocus()
  Protected FensterMitFocus.s = ""
  CompilerIf #PB_Compiler_OS = #PB_OS_Linux
    Protected.i gProgrammId
    gProgrammId = RunProgram("xdotool", "getwindowfocus getwindowname", "", #PB_Program_Open | #PB_Program_Read)
    If gProgrammId
      While ProgramRunning(gProgrammId)
        If AvailableProgramOutput(gProgrammId)
          FensterMitFocus + ReadProgramString(gProgrammId)
        EndIf
      Wend
      CloseProgram(gProgrammId)
      ;
      SetGadgetText(#TextGadget4, "Focus zuvor: " + FensterMitFocus)
      DisableGadget(#ButtonLetzterFocus, #False)
    Else
      MessageRequester("Linux xdotool", "xdotool fehlt, bitte installieren z.B.: apt install xdotool")
    EndIf
  CompilerEndIf
  ProcedureReturn FensterMitFocus.s
EndProcedure
;
Procedure ThreadBedingungBearbeiten(z)
  Static BedingungZustand=0
  While FlagThreadBeenden = #False
    BedingungZustand = BedingungZustand +1
    If BedingungTimer = #False
      If BedingungZustand > 10000    ;ca. 10.000ms
        BedingungZustand = 0
        FensterLetzterFocus.s = WerHatDenFocus()
        FensterOnTop(Fenster.s)
      EndIf
      Delay(1)
    EndIf
  Wend
  ThreadNrTEST = 0
EndProcedure
;
Procedure ZeigeFensterZustand(Zustand)
  If Zustand = -1
    SetGadgetText(#TextGadget3, "Fenster inaktiv")
    SetGadgetColor(#TextGadget3,  #PB_Gadget_BackColor, RGB(255,0,0))
  Else
    SetGadgetText(#TextGadget3, "Fenster aktiv")
    SetGadgetColor(#TextGadget3,  #PB_Gadget_BackColor, RGB(0,255,0))
  EndIf
EndProcedure
;
Procedure ZeigeStickyZustand(Zustand)
  If Zustand = #True    ;bisher als Sticky
    ZustandStickyAktiv = #False
    StickyWindow(#Window_Main, ZustandStickyAktiv) 
    SetGadgetText(#ButtonSticky, "Sticky is OFF")
  Else    ;bisher ohne Sticky
    ZustandStickyAktiv = #True
    StickyWindow(#Window_Main, ZustandStickyAktiv) 
    SetGadgetText(#ButtonSticky, "Sticky is ON")
  EndIf
EndProcedure
;
Procedure ZeigeBedingungZustand(Zustand)
  If Zustand = #True    ;bisher als Timer
    BedingungTimer = #False
    FlagThreadBeenden = #False
    If IsThread(ThreadNrTEST) = 0
      ThreadNrTEST = CreateThread(@ThreadBedingungBearbeiten(), #False)
    EndIf
    SetGadgetText(#ButtonBedingung, "Bedingung is Thread")
  Else    ;bisher als Thread
    FlagThreadBeenden = #True
    BedingungTimer = #True
    SetGadgetText(#ButtonBedingung, "Bedingung is Timer")
  EndIf
EndProcedure
;
Procedure Main()
  Protected EventID, MenueID, GadgetID
  Protected TasteESC = 27
  Protected ZustandFensterAktiv = -1
  If OpenWindow(#Window_Main,10,10,340,300, Fenster.s)
    AddWindowTimer(#Window_Main, #TimerNummerOnTop, 10000)  ;alle 10.000ms.
    AddKeyboardShortcut(#Window_Main, #PB_Shortcut_Escape, TasteESC)
    TextGadget(#TextGadget1, 20, 20, 300, 30, "Bei Focus erhalten, Taste ESC drücken.", #PB_Text_Border) 
    TextGadget(#TextGadget2, 20, 70, 300, 30, "..warte auf ESC-Taste", #PB_Text_Border) 
    ButtonGadget(#ButtonSticky, 20, 110, 120, 30, "Sticky is ON")
    ButtonGadget(#ButtonBedingung, 160, 110, 160, 30, "Bedingung is Timer")
    TextGadget(#TextGadget3, 20, 160, 300, 30, "Fenster aktiv", #PB_Text_Border) 
    ButtonGadget(#ButtonLetzterFocus, 20, 200, 120, 30, "zum letzten Focus")
    DisableGadget(#ButtonLetzterFocus, #True)
    TextGadget(#TextGadget4, 20, 250, 300, 30, "letzter Fokus .......", #PB_Text_Border) 
    ;
    Repeat ; Start of the event loop
      EventID = WaitWindowEvent() 
      GadgetID = EventGadget()
      MenueID = EventMenu()
      ;
      If ZustandFensterAktiv <> GetActiveWindow()
        ZustandFensterAktiv = GetActiveWindow()
        ZeigeFensterZustand(ZustandFensterAktiv)
      EndIf
      
      ;-  Event-Auswertung
      Select EventID
        Case #PB_Event_Timer
          If EventTimer() = #TimerNummerOnTop
            If BedingungTimer = #True
              FensterLetzterFocus.s = WerHatDenFocus()
                FensterOnTop(Fenster.s)
              EndIf
            EndIf
            ;
        Case #PB_Event_Gadget
          If GadgetID = #ButtonSticky
            ZeigeStickyZustand(ZustandStickyAktiv)
          EndIf
          ;
          If GadgetID = #ButtonBedingung
            ZeigeBedingungZustand(BedingungTimer)
          EndIf
          ;
          If GadgetID = #ButtonLetzterFocus
            If FensterLetzterFocus.s <> ""
              FensterOnTop(FensterLetzterFocus.s)
            EndIf
          EndIf
          ;
        Case #PB_Event_Menu
          If MenueID = TasteESC  ;ESC
            SetGadgetText(#TextGadget2, "ESC gedrückt, Zeitpunkt: "+FormatDate("%hh:%ii:%ss", Date()))
          EndIf
      EndSelect
      ;
    Until EventID = #PB_Event_CloseWindow ; End of the event loop
    FlagThreadBeenden = #True
  Else
    Debug "Window konnte nicht geöffnet werden"
  EndIf
EndProcedure
;
Main()
Jürgen
jogo
Beiträge: 64
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint Mate

Re: Focus auf eigenes Fenster setzen

Beitrag von jogo »

super - vielen Dank. :-)
Funktioniert perfekt. Du kennst dich ja wohl auch bestens mit den ganzen Systemtools aus - da steh ich manchmal bissl auf'm Schlauch..
Bin dabei, das alles in mein Timerprojekt reinzufummeln. Mir ist aber jetzt etwas unklar, was das mit dieser Thread-Bedingung auf sich hat.
Wann, wie und warum entscheide ich mich, ob ich Thread- oder Timermodus verwende?
--
Ideen gibt es viele - man muss sie nur haben...
Mint 18.3/19.3/21.x/LMDE5 // PureBasic 5.73 / 6.02
Num500
Beiträge: 19
Registriert: 23.12.2004 18:50
Wohnort: Buchholz

Re: Focus auf eigenes Fenster setzen

Beitrag von Num500 »

Hallo jogo,

das mit dem Thread habe ich nur vorsorglich eingebaut falls sich Deine 'Bedingung'
aus einer Berechnung in dem Programm ergeben sollte statt nur per Timer.
War vielleicht etwas unglücklich weil einen 'Timer' nachgebaut habe.

Wenn Du erst bei erreichen des Timer Deine 'Bedingung' berechnest kannst Du den Thread 'streichen'.

Jürgen
jogo
Beiträge: 64
Registriert: 22.11.2020 20:05
Computerausstattung: 'ne Handvoll gebrauchte Laptops & PCs mit Mint Mate

Re: Focus auf eigenes Fenster setzen

Beitrag von jogo »

achso - ja alles klar, jetzt versteh ich. Natürlich findet das nach einer internen Berechnung statt, nachdem der Timer ausgelöst hat.
Und je nachdem, wie die Berechnung ausfällt, mach ich was und hol mir dann den Focus. (hatte Brett vorm Kopf)
Habe mich durch das Wort 'Thread' verwirren lassen :-)
ok - Danke nochmals bis hierhin
--
Ideen gibt es viele - man muss sie nur haben...
Mint 18.3/19.3/21.x/LMDE5 // PureBasic 5.73 / 6.02
Antworten