Mask of a Gdk::ScrollEvent

I try to handle scroll events on an Gtk::StatusIcon. I woulld like to do
somehing like that

#!/usr/bin/env ruby
###call this script with one argument (a path to an image).
require ‘gtk2’
si=Gtk::StatusIcon.new
si.pixbuf=Gdk::Pixbuf.new(ARGV[0])
si.signal_connect(‘scroll-event’){|icon, event|
p event.state
p event.state.to_i
case event.state
when 0#Empty mask
p ‘scroll event’
p event.direction
when Gdk::window::CONTROL_MASK
p ‘control+scroll event’
end
}
Gtk.main

On my latop, I did not work.
If I use ctrl+scroll, event.state.inspect shows a control mask type but
event.state.to_i==8196 or Gdk::window::CONTROL_MASK.to_i==4. Apparently
the 14th bit of event.state is equal to 1.
http://library.gnome.org/devel/gdk/unstable/gdk-Windows.html#GdkModifierType
tells nothing about this bit.
Why this bit is 1? Will it always be 1?

I could use event.state.inspect and strings in the case statement but it
really seems ugly.

I do not know what to do.

Vincent C. wrote:
I reread gtk doc. It seems that bits 13 and 14 are used by xkb.
For now, I will use a workaround to have bits 13 and 14 equal to 0.

b=event.state.to_i.to_s(2)
b.reverse!;b[13]=0 if b[13];b[14]=0 if b[14];b.reverse!
case b.to_i(2)
when 0

when Gdk::Window::CONTROL_MASK

end

Not very clean but it does not rely on the output of inspect method.

2009/12/8 Vincent C. [email protected]:


end

I think you do not understand how masks should be used.

Here is a working example :
#!/usr/bin/env ruby
#call this script with one argument (a path to an image).
require ‘gtk2’
si = Gtk::StatusIcon.new
si.pixbuf = Gdk::Pixbuf.new(ARGV[0])
si.signal_connect(‘scroll-event’) do |icon, event|
p event.state
p event.direction
case
when (event.state & Gdk::window::CONTROL_MASK) != 0
p ‘control + scroll event’
when (event.state & Gdk::window::SHIFT_MASK) != 0
p ‘shift + scroll event’
else
p ‘scroll only’
end
end
Gtk.main

It works for me. I always have #<Gdk::window::ModifierType mod2-mask>,
which seems to be “numlock”.

If you do not want to manage control/shift/alt, you don’t really care
about it, since you only need direction.

Hope it helps.

Simon

Hi Simon.
Thanks for you reply.

I do want manage crontol/shift… since I want to call different actions
depending on the modifier used.

I understand !(event.state & Gdk::Window::CONTROL_MASK) check if control
is hit. But it do not check if control is the only modifier hit.
Am I wrong?

I think I will have to used a solution close to yours. Cause I cannot be
sure none other modifier (num lock, caps lock…) is pressed.
event.state.control_mask? should be equal to !(event.state &
Gdk::Window::CONTROL_MASK) and it look nicer. :slight_smile:

Thanks for your help.

Simon A. wrote:

Here is a working example :
#!/usr/bin/env ruby
#call this script with one argument (a path to an image).
require ‘gtk2’
si = Gtk::StatusIcon.new
si.pixbuf = Gdk::Pixbuf.new(ARGV[0])
si.signal_connect(‘scroll-event’) do |icon, event|
p event.state
p event.direction
case
when (event.state & Gdk::Window::CONTROL_MASK) != 0
p ‘control + scroll event’
when (event.state & Gdk::Window::SHIFT_MASK) != 0
p ‘shift + scroll event’
else
p ‘scroll only’
end
end
Gtk.main

It works for me. I always have #<Gdk::Window::ModifierType mod2-mask>,
which seems to be “numlock”.

If you do not want to manage control/shift/alt, you don’t really care
about it, since you only need direction.

Hope it helps.

Simon

2009/12/10 Vincent C. [email protected]:

I understand !(event.state & Gdk::window::CONTROL_MASK) check if control
is hit. But it do not check if control is the only modifier hit.
Am I wrong?

You are right, my example was to show you how to use bitmask. It is
not functional :).
I don’t know of syntactic sugar for bitmasks in ruby, so you have to
program almost like in C.

I think I will have to used a solution close to yours. Cause I cannot be
sure none other modifier (num lock, caps lock…) is pressed.
event.state.control_mask? should be equal to !(event.state &
Gdk::window::CONTROL_MASK) and it look nicer. :slight_smile:

I don’t think you need to know what other controls are on or off, you
already know you are in a scroll event, just check the modifier you
want to manage (ctrl, shift, alt, whatever).

If you want to manage ctrl, shift, and ctrl+shift, it would be
something like this:
if (event.state & Gdk::window::CONTROL_MASK) then
code
elif (event.state & Gdk::window::SHIFT_MASK) then
code
elif (event.state & (Gdk::window::CONTROL_MASK|Gdk::window::SHIFT_MASK))
then
code
else
code
end

you could use an empty case also.

Simon

I am currently tring this code :

mask=0; mod=event.state
mask+=1 if mod.control_mask?# 1==20
mask+=2 if mod.shift_mask?# 2==2
1
mask+=4 if mod.mod1_mask?#Alt 4=2**2
case mask
when 0
code
when 1
code
when 2
code
when 3
code

end

It look very similar to yours. Instead of checking the bit mask, I use a
integer corresponding to each bit. After all integer are store binary!
(Not sure I am very clear)
If It does not work, I will try your code.

Thanks for your time.

Simon A. wrote:

I don’t think you need to know what other controls are on or off, you
already know you are in a scroll event, just check the modifier you
want to manage (ctrl, shift, alt, whatever).

If you want to manage ctrl, shift, and ctrl+shift, it would be
something like this:
if (event.state & Gdk::Window::CONTROL_MASK) then
code
elif (event.state & Gdk::Window::SHIFT_MASK) then
code
elif (event.state & (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK))
then
code
else
code
end

you could use an empty case also.

Simon

I did not think about that.
But of course if (event.state &
(Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)) is true,
(event.state & Gdk::Window::CONTROL_MASK) is necessarry true. So we
should check against (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)
first.
Thanks Pascal T. for this fine remark.

Pascal T. wrote:

Le vendredi 11 d�cembre 2009 � 11:02 +0100, Simon A. a �crit :

if (event.state & Gdk::Window::CONTROL_MASK) then
code
elif (event.state & Gdk::Window::SHIFT_MASK) then
code
elif (event.state & (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)) then

This one should be first, else you will never enter it because
event.state & Gdk::Window::CONTROL_MASK will be true

2009/12/11 Vincent C. [email protected]:

 code
when 2
 code
when 3
 code

end

It look very similar to yours. Instead of checking the bit mask, I use a
integer corresponding to each bit. After all integer are store binary!

I did not thought about that. But it’s much simpler than you think :

mask = event.state &
(Gdk::window::CONTROL_MASK|Gdk::window::SHIFT_MASK|…)
case mask
when Gdk::window::CONTROL_MASK
code
when Gdk::window::SHIFT_MASK
code
when Gdk::window::CONTROL_MASK|Gdk::window::SHIFT_MASK
code
end

You could switch to integers, but may gdk changes its mask, very
unlikely, but who knows, it would break.
Taking out verbosity, the code is much understandable imo with the
constants.

And thanks Pascal, my exmaple was terrible indeed :slight_smile:

Simon

If gdk changes its mask, my code should not brake cause the integer is
build with control_mask? and co methods. But you are write your last
code seems more understable. I think I will rewrite my method.

Once again thanks.

Simon A. wrote:

mask = event.state &
(Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK|…)
case mask
when Gdk::Window::CONTROL_MASK
code
when Gdk::Window::SHIFT_MASK
code
when Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK
code
end

You could switch to integers, but may gdk changes its mask, very
unlikely, but who knows, it would break.
Taking out verbosity, the code is much understandable imo with the
constants.

And thanks Pascal, my exmaple was terrible indeed :slight_smile:

Simon

Le vendredi 11 décembre 2009 à 11:02 +0100, Simon A. a écrit :

if (event.state & Gdk::Window::CONTROL_MASK) then
code
elif (event.state & Gdk::Window::SHIFT_MASK) then
code
elif (event.state & (Gdk::Window::CONTROL_MASK|Gdk::Window::SHIFT_MASK)) then

This one should be first, else you will never enter it because
event.state & Gdk::Window::CONTROL_MASK will be true

Hey, could you show your final version, if you don’t mind?

I’d like to collect interesting code (such as this) if it is working. :slight_smile:

Marc H. wrote:

Hey, could you show your final version, if you don’t mind?

I will as soon as it is written.

My “code with integer” works but I finally use Simon code.

#Check only for control, alt and shift.
mask=event.state&(Gdk::Window::CONTROL_MASK|Gdk::Window::MOD1_MASK|Gdk::Window::SHIFT_MASK)
case mask
when 0#no modifier key hit
code
when Gdk::Window::CONTROL_MASK
code
when (Gdk::Window::CONTROL_MASK|dk::Window::MOD1_MASK)
code

end

It works well on my laptop.

Vincent