Autore Topic: Higgins: un lanciatore per gambas  (Letto 2391 volte)

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Higgins: un lanciatore per gambas
« il: 13 Aprile 2016, 15:45:23 »
Sto scrivendo un lanciatore di applicazioni, si chiama "higgins", come il maggiordomo di Magnum Pi :)
https://github.com/kokoko3k/higgins/blob/master/README

Attualmente è in grado di fare calcoli, cercare applicazioni, file (tramite locate), e lanciare comandi eventualmente in un terminale.

Quello che manca, e che vorrei integrare, è la registrazione di hotkey globali, di modo che possa essere richiamato tramite una combinazione di tasti senza l'ausilio di helper esterni (come xbindkeys e quelli integrati in kde).

Non ho trovato nulla nella documentazione ufficiale.
L'unico esempio che ho trovato, questo:
http://gambas.8142.n7.nabble.com/How-to-show-a-form-with-keyboard-shortcut-td25183.html
..Ma parla di programmazione delle Xlib a basso livello, troppo basso per me, ed oltretutto non mi funziona nemmeno.
C'è qualcuno in grado di aiutarmi?

A parte questo, estendo l'invito a chiunque volesse contribuire ad allargare le funzionalità di higgins.
« Ultima modifica: 13 Aprile 2016, 15:48:17 da koko »

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.244
  • Tonno verde
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #1 il: 13 Aprile 2016, 17:42:58 »
Ciao Koko,
ben ritrovato. Miseria fai delle robe... :o
Un po mi scappa da ridere perchè proprio ieri parlando con un ns. collega che si lamentava che con l'aggiornamento del kernel aveva vari problemi fra cui il non funzionamento delle trayicon io gli ho risposto che neanche le sapevo usare, ed ecco che tu me le mostri  :D

Comunque non sono sicuro di saperla far funzionare ma ottengo questo in console quando la chiudo.

Codice: [Seleziona]
gbx3: warning: circular references detected:
gbx3:     1 DBusStatusIcon
gbx3:     1 DBusStatusIconMenu
gbx3:     1 TrayIcon
gbx3:     4 DBusObject
gbx3:     2 Picture
gbx3: warning: 74 allocation(s) non freed.

La ricerca mi riesce ma io di menu vedo solo il Quit.
Ho Ubuntu 14.04

Circa il quesito che poni, non so se sono in grado di aiutarti ma cosa vuoi sapere esattamente delle shortcut?
 :ciao:
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #2 il: 13 Aprile 2016, 18:12:32 »
Ciao e grazie per le lusinghe :)
Non c'è molto da sapere su higgins, dovrebbe/vorrebbe essere semplice come concetto, e se non lo è, allora non funziona bene  ;D

Comunque la trayicon serve solo a uscire dall'applicazione, ecco perchè ottieni solo "quit" dal suo menu,mentre se ci clicchi, mostri la finestra principale.
Per il resto, basta scrivere un termine nella textbox.
I primi risultati proposti sono i file .desktop (i lanciatori); viene effettuata ricerca per nome, descrizione e commento (purtroppo, per adesso solo i termini inglesi.)
E' quindi presumibile che se scrivi "office" avrai qualsiasi programma che tratti file da ufficio; se scrivi "game", avrai tutti i giochi appartenenti alla categoria "game" e così via.
Se hai installato il programma "locate", che indicizza il tuo disco, higgins lo usa per proporti i risultati della ricerca in modo abbastanza veloce.
Per ultimo, se scrivi =4+4 oppure =sin(4)^2, avrai il risultato dell'operazione.

Essendo un launcher, è comodo che l'utente possa lanciarlo con una combinazione di tasti.
Questa dev'essere registrata in X11 come scorciatoia globale, e a quanto pare gambas non implementa questa cosa; per cui bisogna ricorrere alla programmazione di api a più basso livello come quelle di X11.

So che da quel messaggio in uscita, ma non capisco dove mettere le mani per impedirlo;  :hard:; non credo comunque sia grave.
« Ultima modifica: 13 Aprile 2016, 18:22:41 da koko »

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.244
  • Tonno verde
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #3 il: 13 Aprile 2016, 18:19:51 »
Si scusami il tuo programma mi funziona bene.
Trova tutto in un attimo è ottimo.
Non ero riuscito a fare le operazioni matematiche perché non ho pensato agli spreadsheet  ;D

Da una vista rapida del codice avevo frainteso che ci fosse un menu (menu1)

Ora ho capito anche cosa chiedevi circa i tasti rapidi, ma come detto di trayicon nulla saccio Comunque se mi dovesse venire qualche idea io non mi vergogno a dirla.

 :ciao:

PS: Purtroppo l'utente che ti potrebbe aiutare è quello a cui il kernel da problemi, gli altri capaci oramai ci hanno abbandonato  :'(

PS2: Se chiudo la finestra di ricerca e poi tento di riaprirla cliccando sulla trayicon non mi riesce, si tratta di un bug?
« Ultima modifica: 13 Aprile 2016, 18:29:00 da Gianluigi »
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.720
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #4 il: 14 Aprile 2016, 00:41:57 »
..Ma parla di programmazione delle Xlib a basso livello
Nell'esempio lì riportato si utilizzano in Gambas mediante la risorsa Extern le funzioni esterne del API del sistema grafico X11.


Nella nostra WIKI ho riportato qualche pagina con esperimenti di utilizzo della libreria X11, come ad esempio questa:
http://www.gambas-it.org/wiki/index.php?title=Creare_una_finestra_mediante_le_funzioni_del_API_di_X11
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #5 il: 14 Aprile 2016, 18:26:08 »
Ti ringrazio molto ma non ho fatto molti progressi.
il mio codice:
Codice: [Seleziona]
' Gambas class file

Public Struct XEventStruct
  type As Integer
  serial As Long
  send_event As Boolean
  display As Pointer
  windowL As Long
  root As Long
  subwindow As Long
  timeL As Long
  x As Integer
  y As Integer
  x_root As Integer
  y_root As Integer
  state As Integer
  keycode As Integer
  same_screen As Boolean
End Struct

Private Enum KeyPress = 2, KeyRelease, ButtonPress, ButtonRelease, MotionNotify, EnterNotify, LeaveNotify,
                           FocusIn, FocusOut, KeymapNotify, Expose, GraphicsExpose, NoExpose
Private Const ExposureMask As Integer = 32768
Private Const KeyPressMask As Byte = 1
Private Const ButtonPressMask As Byte = 4



Extern XOpenDisplay(DpyName As String) As Pointer In "libX11"
Extern XDefaultScreen(Display As Pointer) As Integer In "libX11"
Extern XDefaultRootWindow(Display As Pointer) As Integer In "libX11"
Extern XSelectInput(Display As Pointer, Window As Integer, KeyMask As Long) In "libX11"
Private Extern XNextEvent(displayP As Pointer, event_return As XEventStruct) In "libX11"
Extern XGrabKey(Display As Pointer, KeyCode As Integer, Modifiers As Integer, Window As Pointer, OwnEvent As Boolean, PointerMode As Integer, KeyboardMode As Integer) In "libX11"
Extern XGrabKeyboard(Display As Pointer, KeyCode As Integer, Modifiers As Integer, Window As Pointer, OwnEvent As Boolean, PointerMode As Integer, KeyboardMode As Integer) In "libX11"
Extern XKeysymToKeycode(Display As Pointer, keysym As Integer) As Integer In "libX11"


Public Sub form_open()
    Dim pDisplay As Pointer
    Dim pRootWindow As Pointer
    Dim pEvent As New XEventStruct
    Dim keycode As Integer
    pDisplay = XOpenDisplay(":0.0")
    pRootWindow = XDefaultRootWindow(pDisplay)
    keycode = XKeysymToKeycode(pDisplay, Asc("y"))
    XGrabKey(pDisplay, keycode, 1, pRootWindow, False, 1, 1) '95 = F11 key, 1 = GrabModeAsync
    XSelectInput(pDisplay, pRootWindow, KeyPressMask)

    Do
        XNextEvent(pDisplay, pEvent)
        Debug pEvent.type
    Loop
End

Mi stampa qualcosa su un display "nested" vuoto come Xephir (sostituendo pDisplay = XOpenDisplay(":1.0"))
E stampa appena premo *qualsiasi* tasto, non solo quello che in teoria avrei registrato ("y").

D'altro canto questo esempio in c:
https://stackoverflow.com/questions/4037230/global-hotkey-with-x11-xlib
Codice: [Seleziona]
#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xutil.h>


using namespace std;


int main()
{
    Display*    dpy     = XOpenDisplay(0);
    Window      root    = DefaultRootWindow(dpy);
    XEvent      ev;

    unsigned int    modifiers       = ControlMask | ShiftMask;
    int             keycode         = XKeysymToKeycode(dpy,XK_Y);
    Window          grab_window     =  root;
    Bool            owner_events    = False;
    int             pointer_mode    = GrabModeAsync;
    int             keyboard_mode   = GrabModeAsync;

    XGrabKey(dpy, keycode, modifiers, grab_window, owner_events, pointer_mode,
             keyboard_mode);

    XSelectInput(dpy, root, KeyPressMask );
    while(true)
    {
        bool shouldQuit = false;
        XNextEvent(dpy, &ev);
        switch(ev.type)
        {
            case KeyPress:
                cout << "Hot key pressed!" << endl;
                XUngrabKey(dpy,keycode,modifiers,grab_window);
                shouldQuit = true;

            default:
                break;
        }

        if(shouldQuit)
            break;
    }

    XCloseDisplay(dpy);
    return 0;
}

...funziona su qualsiasi display, anche quello su cui c'è kwin e kde (avendo cura di battere ctrl-shift-y con il numlock spento); ed io non riesco a capire quale sia la differenza!
« Ultima modifica: 14 Aprile 2016, 18:28:42 da koko »

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.720
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #6 il: 14 Aprile 2016, 18:41:56 »
A me pare non funzioni né l'esempio in Gambas né quello in C++.   ... :-\
« Ultima modifica: 14 Aprile 2016, 18:44:59 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Gianluigi

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 4.244
  • Tonno verde
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #7 il: 14 Aprile 2016, 20:52:58 »
Riguardo agli warnings ho posto il problema sulla ML e Minisini ammette che c'è qualcosa che non va, però con le GTK l'esempio postato pare funzionare.  :-\
 :ciao:
nuoto in attesa del bacio di una principessa che mi trasformi in un gambero azzurro

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #8 il: 18 Aprile 2016, 17:57:08 »
Grazie, lo terrò presente.
Vuott, è strano, con il codice in c a me funge.
occhio al numlock, dev'essere spento perchè anche quello è un modificatore, poi ctrl-shift-y ed il programma stampa ed esce.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.720
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #9 il: 19 Aprile 2016, 01:57:57 »
occhio al numlock, dev'essere spento perchè anche quello è un modificatore
Sì, giusto. Bravo.
Bene, ora il codice in C++ funziona.


Intanto ho rivisto anche il codice in Gambas: ho semplicemente tradotto quel codice funzionante dal C++ in Gambas; e funziona anche questo:
Codice: [Seleziona]
Library "libX11:6.3.0"

Private Enum KeyPress = 2, KeyRelease, ButtonPress, ButtonRelease, MotionNotify, EnterNotify, LeaveNotify,
                           FocusIn, FocusOut, KeymapNotify, Expose, GraphicsExpose, NoExpose
Private Const GrabModeAsync As Integer = 1
Private KeyPressMask As Integer = 1 * CInt(2 ^ 0) '   1L<<0 '
Private ControlMask As Integer = 1 * CInt(2 ^ 2)  '   1<<2  '
Private ShiftMask As Integer = 1 * CInt(2 ^ 0)    '   1<<0  '

' Display *XOpenDisplay(char *display_name)'
' Opens a connection to the X server that controls a display.'
Private Extern XOpenDisplay(display_name As Pointer) As Pointer

' Window XDefaultRootWindow(Display *display)'
' Returns the root window for the default screen.'
Private Extern XDefaultRootWindow(display As Pointer) As Integer

' KeyCode XKeysymToKeycode(Display *display, KeySym keysym)'
' Obtains a KeyCode for a key having a specific KeySym.'
Private Extern XKeysymToKeycode(display As Pointer, keysym As Integer) As Integer

' XGrabKey(Display *display, int keycode, unsigned int modifiers, Window grab_window, Bool owner_events, int pointer_mode, int keyboard_mode)'
' Passively grabs a single key of the keyboard.'
Private Extern XGrabKey(display As Pointer, keycode As Integer, modifiers As Integer, grab_window As Integer, owner_events As Boolean, pointermode As Integer, keyboard_mode As Integer)

' XSelectInput(Display *display, Window w, long event_mask)'
' Requests that the X server report the events associated with the specified event mask.'
Private Extern XSelectInput(display As Pointer, w As Integer, event_mask As Long)

' XNextEvent(Display *display, XEvent *event_return)'
' Gets the next event and remove it from the queue.'
Private Extern XNextEvent(display As Pointer, event_return As Pointer)

' XUngrabKey(Display *display, int keycode, unsigned int modifiers, Window grab_window)'
' Ungrabs a key.'
Private Extern XUngrabKey(display As Pointer, keycode As Integer, modifiers As Integer, Window As Pointer)

' XCloseDisplay(Display *display)'
' Closes a display or disconnects from the X server.'
Private Extern XCloseDisplay(display As Pointer)


Public Sub Main()

  Dim dpy As Pointer
  Dim root As Integer
  Dim ev As Pointer
  Dim keycode As Integer

    ev = Alloc(192)

    dpy = XOpenDisplay(0)
   
    root = XDefaultRootWindow(dpy)

    keycode = XKeysymToKeycode(dpy, Asc("y"))

    XGrabKey(dpy, keycode, ControlMask Or ShiftMask, root, False, GrabModeAsync, GrabModeAsync)
   
    XSelectInput(dpy, root, KeyPressMask)

    While True
      XNextEvent(dpy, ev)
      Select Case Int@(ev)
        Case KeyPress
          Print "Hot key pressed !"
          XUngrabKey(dpy, keycode, ControlMask Or ShiftMask, root)
          Break
      End Select
    Wend

    Free(ev)
    XCloseDisplay(dpy)

End
« Ultima modifica: 19 Aprile 2016, 13:45:14 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #10 il: 19 Aprile 2016, 08:27:37 »
Grazie vuott, il tuo codice sembra funzionare senza problemi.
Ora la missione è capire perchè il mio non andava :)
-EDIT-
Ok, era qualcosa riguardante la maschera in XgrabKey() mettendo la tua maschera, funge senza problemi.
« Ultima modifica: 19 Aprile 2016, 08:32:09 da koko »

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.720
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #11 il: 19 Aprile 2016, 08:50:09 »
Io proprio non riesco a capire  :-\ come quel codice Gambas iniziale potesse funzionare: c'erano - fra l'altro - pure valori discordanti dall'esempio in C++ .
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #12 il: 19 Aprile 2016, 08:53:41 »
Se non ci riesci tu, io non ho speranze, quando uso le extern il 99% delle volte ottengo dei crash :)

Offline koko

  • Gambero
  • **
  • Post: 52
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #13 il: 19 Aprile 2016, 11:37:33 »
Vabeh, fermo restando il fascino della programmazione Xlib, mi sono scontrato con l'ulteriore problema di dover memorizzare una hotkey secondo la preferenza dell'utente, e da qui ho deciso di abbandonare la vecchia strata (grazie comunque Vuott).
Ne è uscita l'integrazione con xbindkeys che posto qui sotto:

Classe xbindkeys:
Codice: [Seleziona]
' Gambas class file

Private xbindkeysp As Process
Private conf_file As String
Private hotkeys As Collection


Public Sub _new(conf As String)
  If Not System.Exist("xbindkeys") Then
    Debug "ERROR: xbindkeys not found in system path"
    Quit
  Endif
  conf_file = conf
  hotkeys = parse_conf()
  If hotkeys = Null Then hotkeys = New Collection
  Reload_xbindkeys()
End

Private Function parse_conf() As Collection
  Dim pHotKeys As New Collection
  Dim aLine As String
  Dim WhatToDo As String 'find_new,find_action,find_hotkey
  Dim action, hotkey As String
  'Syntax:
  '#new
  'Action
  'hotkey
  If Not Exist(conf_file, True) Then Return Null
  WhatToDo = "find_new"
  For Each aLine In Split(File.Load(conf_file), "\n", "", True)
    Select WhatToDo
      Case "find_new"
        If aLine = "#new" Then WhatToDo = "find_action"
      Case "find_action"
        action = aLine
        WhatToDo = "find_hotkey"
      Case "find_hotkey"
        hotkey = aLine
        pHotkeys[hotkey] = action
        WhatToDo = "find_new"
    End Select
  Next
  Return pHotKeys
End

Private Sub write_conf()
  Dim outfile As String
  Dim action As String
  Dim HotKey As String
  For Each Action In hotkeys
    hotkey = hotkeys.key
    outfile &= "#new" & "\n"
    outfile &= Action & "\n"
    outfile &= Hotkey & "\n"
  Next
  File.Save(conf_file, outfile)
End

Public Sub register(action As String) As String
  Dim tmp As String = Temp()
  Dim out As String
  Dim splitted As String[]
  Dim hotkey As String
  Shell "touch " & tmp Wait
  xbindkeysp.kill
  Shell System.Find("xbindkeys") & " -k -f " & tmp To out
  splitted = Split(out, "\n", "", True)
  hotkey = Trim(splitted[splitted.count - 1])
  hotkeys[hotkey] = "\"" & "echo " & action & "\""
  write_conf()
  Reload_xbindkeys()
  Return hotkey
End

Public Sub close()
  Try xbindkeysp.kill
End

Public Sub Reload_xbindkeys()
  Try xbindkeysp.kill
  xbindkeysp = Shell "xbindkeys -n -f " & conf_file For Read As "xbindkeysp"
End

Event HotkeyPressed(action As String)

Public Sub xbindkeysp_read()
  Dim out As String
  Line Input #xbindkeysp, out
  Raise Hotkeypressed(out)
End

Utilizzatore della classe (esempio)
Codice: [Seleziona]
Public xb As XbindKeys

Public Sub Form_Open()
  xb = New XbindKeys("/tmp/y") As "xb"
End

Public Sub Button1_Click()
  xb.register("Prova_action")
End

Public Sub Form_Close()
  xb.close
End

Public Sub xb_HotkeyPressed(action As String)
  Debug action
End

In sostanza si instanzia un processo xbindkeys, si possono definire nuove hotkey associate a semplici stringhe che ritorneranno al programma principale tramite l'evento _HotkeyPressed.
Manca il codice per rimuovere una hotkey o una azione.
« Ultima modifica: 19 Aprile 2016, 11:38:21 da koko »

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.720
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Higgins: un lanciatore per gambas
« Risposta #14 il: 21 Aprile 2016, 02:43:15 »
Ora la missione è capire perchè il mio non andava
-EDIT-
Ok, era qualcosa riguardante la maschera in XgrabKey() mettendo la tua maschera, funge senza problemi.

...relativamente a quella funzione esterna:
* il 3° argomento è = 5 e non 1;
* il 4° argomento è un Intero e non un Puntatore.
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »