Forum: Ruby-Gnome 2 mask of a Gdk::ScrollEvent

Posted by Vincent Carmona (vinc-mai)
on 2009-12-08 22:04
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.
Posted by Vincent Carmona (vinc-mai)
on 2009-12-08 23:30
Vincent Carmona 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.
Posted by Simon Arnaud (Guest)
on 2009-12-09 12:32
(Received via mailing list)
2009/12/8 Vincent Carmona <ruby-forum-incoming@andreas-s.net>:
> ...
> 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
Posted by Vincent Carmona (vinc-mai)
on 2009-12-10 18:24
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. :)

Thanks for your help.

Simon Arnaud 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
Posted by Simon Arnaud (Guest)
on 2009-12-11 11:03
(Received via mailing list)
2009/12/10 Vincent Carmona <ruby-forum-incoming@andreas-s.net>:
> 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. :)

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
Posted by Vincent Carmona (vinc-mai)
on 2009-12-11 11:46
I am currently tring this code :

mask=0; mod=event.state
mask+=1 if mod.control_mask?#   1==2**0
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 Arnaud 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
Posted by Pascal Terjan (Guest)
on 2009-12-11 11:55
(Received via mailing list)
Le vendredi 11 décembre 2009 à 11:02 +0100, Simon Arnaud 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
Posted by Vincent Carmona (vinc-mai)
on 2009-12-11 12:07
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 Terjan for this fine remark.

Pascal Terjan wrote:
> Le vendredi 11 d�cembre 2009 � 11:02 +0100, Simon Arnaud 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
Posted by Simon Arnaud (Guest)
on 2009-12-11 12:44
(Received via mailing list)
2009/12/11 Vincent Carmona <ruby-forum-incoming@andreas-s.net>:
>  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 :)

Simon
Posted by Vincent Carmona (vinc-mai)
on 2009-12-11 13:11
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 Arnaud 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 :)
> 
> Simon
Posted by Marc Heiler (shevegen)
on 2009-12-12 04:27
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. :)
Posted by Vincent Carmona (vinc-mai)
on 2009-12-12 21:13
Marc Heiler wrote:
> Hey, could you show your final version, if you don't mind?

I will as soon as it is written.
Posted by Vincent Carmona (vinc-mai)
on 2009-12-13 01:33
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
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.