GtkDialog - How to Perform function conditionally? [SOLVED]

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

GtkDialog - How to Perform function conditionally? [SOLVED]

#1 Post by MochiMoppel »

Assuming that varname is the name of a widget variable, then this will execute the given command only when key K is pressed

Code: Select all

<action signal="key-press-event">[ $KEY_VAL = "0x06b" ] && gxmessage $varname</action>
How can I do this for a function? This will obviously not work:

Code: Select all

<action signal="key-press-event">[ $KEY_VAL = "0x06b" ] && Refresh:varname</action>
Any ideas how this can by done with <action> ?


------------
Last edited by MochiMoppel on Thu 12 Jun 2014, 05:41, edited 2 times in total.

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#2 Post by SFR »

This will work (req. Gtkdialog >= 0.8.3):

Code: Select all

<action signal="key-press-event" condition="command_is_true( [ $KEY_VAL = 0x06b ] && echo true )">Refresh:varname</action>
Btw, if you want quotes around $KEY_VAL or 0x06b, they need to be escaped: \"$KEY_VAL\".

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#3 Post by MochiMoppel »

Domo arigato! That helps me a lot. The && echo true seems to be irrelevant. [ $KEY_VAL = 0x06b ] already returns true, so no need for anything else. IMO echo something always returns true, so there is nothing to gain from it, or is it ?

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#4 Post by SFR »

And does it work for you this way?
It never worked for me, no-go without && echo true, I don't know why...
Perhaps there need to be literal string "true"..? :?

Anyway, glad could help. :)

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#5 Post by MochiMoppel »

You are right, it doesn't work this way :oops:

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#6 Post by SFR »

Ah, there's an explanation on Gtkdialog's wiki (any widget):
true means "true", "yes" or a non-zero value, false means "false", "no" or zero, therefore the shell command is expected to echo one of these values to stdout.
One mystery down. ;)

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#7 Post by MochiMoppel »

I was just reading the same in the wiki, but now the mystery continues: How did you find out even without having read the terse documentation? Intuition?

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#8 Post by SFR »

I wish I had such an intuition. :lol:
I guess I saw this for the first time (in practice) in eventmanager, which I was workin on, adding some features at that time:
https://github.com/puppylinux-woof-CE/w ... #L310-L319

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#9 Post by MochiMoppel »

Thanks for the link. Good stuff!

Did your intuitive investigatiion by any chance led you to a solution for key-press events involving modifier keys? Would be nice to perform actions upon pressing Ctrl+K. My guess is that this is the end of the line for <action>.
My current workaround uses <menuitem> with accel-key and accel-mods, packed into an invisible menu bar. Works pretty well, is much more readable and doesn't require gtkdialog4, but after all it's a workaround.

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#10 Post by SFR »

Did your intuitive investigatiion by any chance led you to a solution for key-press events involving modifier keys? Would be nice to perform actions upon pressing Ctrl+K. My guess is that this is the end of the line for <action>.
Yes, in this case it was indeed my intuition + /usr/share/doc/gtkdialog/examples/miscellaneous/press_and_release_events example, which is very helpful to determine correct values.

An example:

Code: Select all

#!/bin/bash

# Ctrl+Shift+R to refresh the date

export MAIN='
<window>
  <text>
    <variable>varDATE</variable>
    <input>date</input>
  </text>
  <action signal="key-press-event" condition="command_is_true( [ $(( ${KEY_MOD} & 5 )) = 5 ] && [ $KEY_RAW = 0x1b ] && echo true )">Refresh:varDATE</action>
</window>'

gtkdialog -cp MAIN
Some explanations: SHIFT's state is held by by 0th bit and CTRL state by 2nd bit of $KEY_MOD variable (?????C?S) , so, in order to read their state correctly, we need to discard the rest of bits by logical AND: $(( $KEY_MOD & 5 )).
If we would want SHIFT alone, it would be $(( $KEY_MOD & 1)) = 1, only CTRL - $(( $KEY_MOD & 4 )) = 4 and so on.
(I hope it's clear enough?)
My current workaround uses <menuitem> with accel-key and accel-mods, packed into an invisible menu bar. Works pretty well, is much more readable and doesn't require gtkdialog4, but after all it's a workaround.
And this is very good workaround in some cases!
For example, I needed simple terminal that is divided into three sections (upper and lower on first tab and one big on the second) and I used exacly the same method to switch between them (Ctrl+1,2,3).
Using the $KEY... method in this case failed, because, regardless of various combinations that I tried, there was always some undesired character (usually "1") printed in one of the areas, while switching between them.
The only downside is that F10 is always being intercepted by this menu widget, no matter what...

Here's the code, btw, if anyone's interested (req. Gtkdialog >= 0.8.3 with VTE):

Code: Select all

#!/bin/sh

# TriTerm v0.1 by SFR'2014

APPNAME="TriTerm v0.1"
CWD=`pwd`

export INDEX=/dev/shm/triterm_index_${$}
echo 0 > $INDEX
trap 'rm $INDEX' EXIT

#==============================================================================

func_term () {
echo '
<terminal argv0="/bin/bash"
          current-directory-uri="'${CWD}'"
          encoding="UTF-8"
	      cursor-shape="0"
          scrollback-lines="10000"
  	      font-name="10"
    	  text-background-color="#fff"
  	      text-foreground-color="#000"
  	      cursor-background-color="#888"
          hscrollbar-policy="1"
          vscrollbar-policy="0">
  <variable>varTERM_'${1}'</variable>
  <width>83</width>
  <height>16</height>
  <action signal="child-exited">exit:EXIT</action>
</terminal>'
}

#==============================================================================

[ -e "/usr/local/lib/X11/mini-icons/mini-sh.xpm" ] && PIX_PATH="/usr/local/lib/X11/mini-icons/mini-sh.xpm" || PIX_PATH="/usr/share/pixmaps/puppy/terminal.svg"

export MAIN='
<window title="'${APPNAME}'" image-name="'${PIX_PATH}'">
  <vbox space-fill="true" space-expand="true">
    <notebook show-tabs="false">
      <vbox>
        '"`func_term 1`"'
        '"`func_term 2`"'     
      </vbox>
  
      <vbox>
        '"`func_term 3`"'
      </vbox>
  
      <variable>varPAGE</variable>
      <input file>'${INDEX}'</input>
    </notebook>

    <vbox space-fill="false" space-expand="false">
      <menubar height-request="1" width-request="1">
        <menu>
          <menuitem accel-key="0x31" accel-mods="4">
            <label>Top Terminal</label>
            <action>echo 0 > '${INDEX}'</action>
            <action>refresh:varPAGE</action>
            <action>grabfocus:varTERM_1</action>
          </menuitem>
          <menuitem accel-key="0x32" accel-mods="4">
            <label>Bottom Terminal</label>
            <action>echo 0 > '${INDEX}'</action>
            <action>refresh:varPAGE</action>
            <action>grabfocus:varTERM_2</action>
          </menuitem>
          <menuitem accel-key="0x33" accel-mods="4"> 
            <label>Full Terminal</label>
            <action>echo 1 > '${INDEX}'</action>
            <action>refresh:varPAGE</action>
            <action>grabfocus:varTERM_3</action>
          </menuitem>
          <label>""</label>
        </menu>
      </menubar>
    </vbox>
  </vbox>
<action signal="delete-event">exit:abort</action>
</window>'

#==============================================================================

gtkdialog -p MAIN
exit
Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#11 Post by zigbert »

Code: Select all

<action signal="key-press-event" condition="command_is_true( [ $(( ${KEY_MOD} & 5 )) = 5 ] && [ $KEY_RAW = 0x1b ] && echo true )">Refresh:varDATE</action> 
Like it :)


Thank you
Sigmund

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#12 Post by MochiMoppel »

zigbert, in his GtkDialog-Tips thread, wrote:Hotkeys
>> An <action> signal inside the <window> widget gives the most direct hotkey
<action signal="key-press-event" condition="command_is_true( [ $(( ${KEY_MOD} & 5 )) = 5 ] && [ $KEY_RAW = 0x1b ] && echo true )">Refresh:varDATE</action>
Some explanations: SHIFT's state is held by by 0th bit and CTRL state by 2nd bit of $KEY_MOD variable (?????C?S) , so, in order to read their state correctly, we need to discard the rest of bits by logical AND: $(( $KEY_MOD & 5 )).
If we would want SHIFT alone, it would be $(( $KEY_MOD & 1)) = 1, only CTRL - $(( $KEY_MOD & 4 )) = 4 and so on.

>> Menuitems can set both accelerator key and modifier (SHIFT is 1, CTRL is 4 and ALT is 8 ). For a full list of accelerator key values check this
<menuitem stock-id="gtk-quit" accel-key="0x51" accel-mods="4">
A hidden menubar gives you nice solution
@zigbert. You are quick. I see that you already edited your valuable GtkDialog-Tips, but frankly I'm not sure if this is understandable for simple minded non-nerds like me. Not everybody is familiar with bitwise logical operations and I am still struggling with SFR's example. I'm sure you like it, but before I can see the beauty in this beast I want to understand it. Maybe you should wait until my problems are solved ( I need 1 or 2 more days for testing) and then, after even MochiMoppel understands this stuff, you can be sure that the explanations are foolproof.

Also the remark about the hidden menubar can be misleading. A hidden menubar is not a nice solution at all because the hotkeys will not work :cry: The menubar needs to be visible. What I meant in my casual remark is that I use a de-facto invisible menu: 1x1px size. Depending on color theme this single dot will be rendered in the same color as the surrounding area, which makes is invisible. Maybe there are better solutions.

Speaking about your thread, which was the starting point for my gtkdialog endeavors: In the list of menuitem modifier keys, could you please include modifier 0 (zero)? Since hotkeys for menuitem must include modifier keys, the present information gives the impression that single key hotkeys are impossible. It took me quite a while to find out that single hotkeys can be realized with a "no modifier" modifier, e.g hotkey for the single DEL key would be accel-key="0xffff" accel-mods="0"
Also I would like to see a short remark, how to combine modifier keys. There is one in the wiki which I found very nerdy ("1. SHIFT is 1, CTRL is 4 and ALT is 8 and you can OR them together.") Made me feel really stupid since I had no idea how to simply "OR them together". Maybe "add the values" doesn't sound cool enough :wink:

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#13 Post by SFR »

I'll try to shed more light on the issue. ;)

Unfortunately, due to technical difficulties (problems with precise aligning), the rest of this post is in the attached .txt file.

Greetings!
Attachments
KEY_MOD_post.txt.gz
.gz is a fake, it's a plain text
(3.4 KiB) Downloaded 396 times
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#14 Post by MochiMoppel »

Excellent! :D
After slowly getting to grips with this stuff the only question that puzzled me was why the (none) mode would always be 00010000. Ahhh...NumLock ! Your table made it clear. As for me this part is clear now. Thanks a lot.

Regarding the key value I'm not sure if KEY_RAW is a good choice as it depends on HW and keyboard layout. KEY_RAW = 0x1b may render an R on a US keyboard, but a P on Dvorak keyboard. So far I used KEY_VAL because I could easily look the value up with xev , but KEY_SYM = R seems so much simpler and readable. Are there reasons to avoid it?

Regarding + /usr/share/doc/gtkdialog/examples: I don't have this installed. It's not standard and it's not included in gtkdialog pets. I do have a local copy on my HD, but it's pretty old and I would love to download the newest version. Unfortunately I can't find a link anywhere. Where can I get it?

So many question. Thanks for being patient.

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#15 Post by SFR »

Yeah, KEY_SYM/KEY_VAL might be indeed a better choice, just note that if SHIFT is pressed, the output values/characters reflect the difference (unlike KEY_RAW), e.g.:

Only A:
KEY_RAW=0x26, KEY_VAL=0x061, KEY_SYM=a

SHIFT+A:
KEY_RAW=0x26, KEY_VAL=0x041, KEY_SYM=A

/usr/share/doc/gtkdialog/examples should be in devx_xxx.sfs, but here's the online version:
http://gtkdialog.googlecode.com/svn/trunk/examples
http://gtkdialog.googlecode.com/svn/tru ... ase_events

Btw, I found also this, which describes KEY_MOD values more generally:
http://gtk.php.net/manual/en/html/gdk/g ... rtype.html
(I think we can ignore all stuff >= 256)
[Hmm, if this page is loading way too long, just press "Stop" button in your browser and the contents should appear]

In my case the modifiers, described on the above page, look like:

Code: Select all

sh-4.1# xmodmap -pm
xmodmap:  up to 3 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x6d)
mod1        Alt_L (0x40),  Alt_L (0x7d),  Meta_L (0x9c)
mod2        Num_Lock (0x4d)
mod3      
mod4        Super_L (0x7f),  Hyper_L (0x80)
mod5        Mode_switch (0x5d),  ISO_Level3_Shift (0x71),  ISO_Level3_Shift (0x7c)

sh-4.1# 
Can't locate mod4, but mod5 is AltGr on my keyboard.

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#16 Post by MochiMoppel »

SFR wrote:Yeah, KEY_SYM/KEY_VAL might be indeed a better choice, just note that if SHIFT is pressed, the output values/characters reflect the difference (unlike KEY_RAW)
I know, but that's rather an advantage. We may not need the extra check for the Shift status:

Code: Select all

<action signal="key-press-event"> [ $KEY_SYM = A ] && xmessage " Shift+A pressed"</action>
<action signal="key-press-event"> [ $KEY_SYM = a ] && xmessage " A pressed"</action>
/usr/share/doc/gtkdialog/examples should be in devx_xxx.sfs, but here's the online version:
Thanks for this hint. I seldom load devx_xxx.sfs and I haven't noticed, but I swear I downloaded it from somewhere else...
Reading the reference online is OK, but having the examples only online is a bit cumbersome. I found a slightly old package which might be worth downloading just for the examples it includes. I'm sure there are others: https://www.archlinux.org/packages/comm ... gtkdialog/

EDIT 1
If we would want SHIFT alone, it would be $(( $KEY_MOD & 1)) = 1, only CTRL - $(( $KEY_MOD & 4 )) = 4 and so on.
(I hope it's clear enough?)
Well, finally it seemed to be clear, but unfortunately it doesn't produce the expected result. $(( $KEY_MOD & 1)) = 1 checks it the Shift bit is set and and judging from the formula it doesn't care about the other modifier bits, but when running your example with this condition the variable is refreshed in cases of Shift+R, Ctrl+Shift+R, Alt+Shift+R etc. , likewise your original example refreshes in case of Crtl+Shift+Alt+R :cry:

Compare this to the rock solid behavior of my usual menubar approach:

Code: Select all

#!/bin/sh
# Shift+R to refresh the date 
export MAIN=' 
 <window> 
  <vbox>
    <hbox>
      <menubar width-request="1" height-request="1">
        <menu>
          <menuitem accel-key="0x52" accel-mods="1"> 
            <action>Refresh:varDATE</action>
          </menuitem>
        </menu>
      </menubar>
    </hbox>
   <text> 
     <variable>varDATE</variable> 
     <input>date</input> 
   </text> 
  </vbox>
 </window>' 

 gtkdialog -cp MAIN
1) In contrast to the key-press-event solution it doesn't matter whether I use accel-key="0x52" (small r) or accel-key="0x72" (capital R). Both work the same. Quite amazing.
2) Of course the variable refreshes only when Shift+R was pressed
3) Needs a bit more boxes, but makes multiple actions and functions easy. With the condition set in <menuitem> and therefore out of the way, all following actions are easy to read and maintain.
4) Usually I set <menu use-underline="true"> and add <label>"_M"</label> to the menu section. Then upon hitting Alt+M the menu pops out of nowhere. At least during development useful for testing the correct assignment of the accel-keys .


There are some downsides...that's why I'm still very much interested in making the key-press-event solution work

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#17 Post by SFR »

MochiMoppel wrote:$(( $KEY_MOD & 1)) = 1 checks it the Shift bit is set and and judging from the formula it doesn't care about the other modifier bits, but when running your example with this condition the variable is refreshed in cases of Shift+R, Ctrl+Shift+R, Alt+Shift+R etc. , likewise your original example refreshes in case of Crtl+Shift+Alt+R
Yep, that's exactly what I mentioned in the attached txt. 8)
me wrote:The above method has a flaw though. If we want to probe e.g. SHIFT+some_key, discarding all other bits will return positive results also if
SHIFT+CTRL+some_key or SHIFT+ALT+some_key or SHIFT+CTRL+ALT+some_key (and so on) are pressed.

So, I think that best solution is to discard only NUMLOCK's, CAPSLOCK's (and those two unknown bits') states, in which case the AND mask will be always constant: 10001101 (141), and only the value we comparing it with will vary.
However, knowing now (more or less) what those two "unknown" bits are, I think it's enough to discard only NumLock, CapsLock and Mod3 (which appears to be Scroll_Lock, not enabled by default in Puppy though).
So, $(( $KEY_MOD & 205 )) = 1 will do the job properly.
MochiMoppel wrote:4) Usually I set <menu use-underline="true"> and add <label>"_M"</label> to the menu section. Then upon hitting Alt+M the menu pops out of nowhere. At least during development useful for testing the correct assignment of the accel-keys .
F10 has the same effect in my case.
Actually, I'd like to disable it, but nothing from what I have found does work. :roll:

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
MochiMoppel
Posts: 2084
Joined: Wed 26 Jan 2011, 09:06
Location: Japan

#18 Post by MochiMoppel »

SFR wrote:F10 has the same effect in my case.
Actually, I'd like to disable it, but nothing from what I have found does work. :roll:
Seems to be a gtk default thing. If you use JWM you can override it with a dummy shortcut. <Key key="F10">exec:</Key> works for me.

User avatar
SFR
Posts: 1800
Joined: Wed 26 Oct 2011, 21:52

#19 Post by SFR »

Thanks, I did not think of that. Alas it disables this shortcut completely and (clarifying the problem) the real PITA is that F10 overrides application's specific shortcuts, e.g. in RoxTerm or LxTerminal there's no way to quit htop or MidnightCommander using F10, because it opens terminal's "File" menu instead.

Well, I found this on several forums (to be put in ~/.gtkrc-2.0):

Code: Select all

binding "NoKeyboardNavigation" {
    unbind "<shift>F10"
}

class "*" binding "NoKeyboardNavigation"
and it apparently works for most of folks, but not for me (with or without <shift>).

Greetings!
[color=red][size=75][O]bdurate [R]ules [D]estroy [E]nthusiastic [R]ebels => [C]reative [H]umans [A]lways [O]pen [S]ource[/size][/color]
[b][color=green]Omnia mea mecum porto.[/color][/b]

User avatar
zigbert
Posts: 6621
Joined: Wed 29 Mar 2006, 18:13
Location: Valåmoen, Norway
Contact:

#20 Post by zigbert »

I have linked to this thread from the 'Gtkdialog Tips' thread.

Post Reply