New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scrolling with mousewheel on a scrollbar within a stack is not working #42

Closed
BackOrder opened this Issue Jan 24, 2015 · 13 comments

Comments

Projects
None yet
3 participants
@BackOrder
Collaborator

BackOrder commented Jan 24, 2015

A scrollbar associated with a stack when using :scroll => true will not allow mouse scroll to scroll up and down. On Windows, it is possible to scroll with the mouse when the cursor is over the scrollbar. On MacOS X, it doesn't scroll with the mouse either way.

Shoes.app {
   stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
   }
}

SHOES APP SCROLLBAR
The scrollbar is fully scrollable when it is on Shoes.app level.

Shoes.app {
   stack {
      (0..100).each { |n| para "#{n}\n" }
   }
}
@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Jan 25, 2015

Collaborator

Duplicate #5 and shoes#178.

Collaborator

BackOrder commented Jan 25, 2015

Duplicate #5 and shoes#178.

@BackOrder BackOrder changed the title from Mouse scroll on a scrollbar within a stack is not working to Scrolling with mousewheel on a scrollbar within a stack is not working Jan 25, 2015

@BackOrder BackOrder added the Linux label Jan 25, 2015

@BackOrder BackOrder referenced this issue Jan 25, 2015

Closed

Mousewheel #5

@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Jan 26, 2015

Collaborator

The following code snippet shows an interesting behaviour on Windows. It creates two overlapping scrollbars one of top of the other. Scrolling with the mousewheel is possible but as you scroll it fights to decide which scrollbars, which contents, to scroll.

@a = Shoes.app {
   @s = stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
   }
   para @s.contents
}
Collaborator

BackOrder commented Jan 26, 2015

The following code snippet shows an interesting behaviour on Windows. It creates two overlapping scrollbars one of top of the other. Scrolling with the mousewheel is possible but as you scroll it fights to decide which scrollbars, which contents, to scroll.

@a = Shoes.app {
   @s = stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
   }
   para @s.contents
}
@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Feb 6, 2015

Contributor

so far only one ugly workaround

Shoes.app do
    @s = stack(height: app.slot.height, scroll: true) do
        (0..100).each { |n| para "#{n}\n" }
    end
    @s.start {|me| 
        info "me.scroll_height = #{me.scroll_height}" # = 6060
        me.height = me.scroll_height
    }
    # app knows nothing about @s.scroll_height yet
    info "@s.scroll_height = #{@s.scroll_height}" # = 0
end

i tried various variations with @s.scroll = true or @s.style(scroll: true) and timer/start without luck ...
looks like scroll is working with what scroll_height value is avalaible at the slot declaration (btw same problem whether it is a stack or a flow) here : app.slot.height, if you assign whatever else value scroll will work with that value in the future

me.height = me.scroll_heigh has nothing to do with the slot scroll style (it works with or without the scroll style)

PS note that method "scroll=" is missing in the manual

Contributor

passenger94 commented Feb 6, 2015

so far only one ugly workaround

Shoes.app do
    @s = stack(height: app.slot.height, scroll: true) do
        (0..100).each { |n| para "#{n}\n" }
    end
    @s.start {|me| 
        info "me.scroll_height = #{me.scroll_height}" # = 6060
        me.height = me.scroll_height
    }
    # app knows nothing about @s.scroll_height yet
    info "@s.scroll_height = #{@s.scroll_height}" # = 0
end

i tried various variations with @s.scroll = true or @s.style(scroll: true) and timer/start without luck ...
looks like scroll is working with what scroll_height value is avalaible at the slot declaration (btw same problem whether it is a stack or a flow) here : app.slot.height, if you assign whatever else value scroll will work with that value in the future

me.height = me.scroll_heigh has nothing to do with the slot scroll style (it works with or without the scroll style)

PS note that method "scroll=" is missing in the manual

@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Feb 6, 2015

Collaborator

This is a great find, @passenger94. It can be simplified as follow:

Shoes.app {
   @s = stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
      timer(0) { @s.height = @s.scroll_height }
   }
}

The challenge is getting it to work when there are other elements on screen. The experimental log window has the console banner always on top. Now the solution might need tweaking as you will see below:

Shoes.app {
   @h = stack(:height => 100) { }
   @s = stack(:height => app.slot.height - 100, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
      timer(0) { @s.height = app.slot.height - 100}
   }
}

Do you mean :scroll => true ? This is a style and is available in the manual.

Collaborator

BackOrder commented Feb 6, 2015

This is a great find, @passenger94. It can be simplified as follow:

Shoes.app {
   @s = stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
      timer(0) { @s.height = @s.scroll_height }
   }
}

The challenge is getting it to work when there are other elements on screen. The experimental log window has the console banner always on top. Now the solution might need tweaking as you will see below:

Shoes.app {
   @h = stack(:height => 100) { }
   @s = stack(:height => app.slot.height - 100, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
      timer(0) { @s.height = app.slot.height - 100}
   }
}

Do you mean :scroll => true ? This is a style and is available in the manual.

@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Feb 7, 2015

Contributor

no,no i mean method scroll=
besides the style :scroll => true there is a getter method scroll which returns true or false - Slots Position area in the manual - but i found an undocumented setter method scroll= which as expected sets the style accordingly

i've tried

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { @s.height = @s.scroll_height - 100}
    }
}

kinda works but with an interesting big mess of overlapping scrolbars !?!

without the scroll style it works on my system
but not your more sophisticated experimental log window

Contributor

passenger94 commented Feb 7, 2015

no,no i mean method scroll=
besides the style :scroll => true there is a getter method scroll which returns true or false - Slots Position area in the manual - but i found an undocumented setter method scroll= which as expected sets the style accordingly

i've tried

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { @s.height = @s.scroll_height - 100}
    }
}

kinda works but with an interesting big mess of overlapping scrolbars !?!

without the scroll style it works on my system
but not your more sophisticated experimental log window

@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Feb 7, 2015

Contributor

this one works better ! no need to substact the height of the first slot of the scroll_height value of the second slot !!! sorry

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { @s.height = @s.scroll_height}
    }
}

but now i can't make it autoscroll !! This doesn't work (both places for timer)

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { 
            @s.height = @s.scroll_height 
            @s.scroll_top = @s.scroll_max
        }

    }
    #timer(0) { @s.scroll_top = @s.scroll_max }
}
Contributor

passenger94 commented Feb 7, 2015

this one works better ! no need to substact the height of the first slot of the scroll_height value of the second slot !!! sorry

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { @s.height = @s.scroll_height}
    }
}

but now i can't make it autoscroll !! This doesn't work (both places for timer)

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { 
            @s.height = @s.scroll_height 
            @s.scroll_top = @s.scroll_max
        }

    }
    #timer(0) { @s.scroll_top = @s.scroll_max }
}
@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Feb 8, 2015

Collaborator

Your results are similar to mine. @ccoupe and I talked a little about the implementation and it seems that the wheel events are properly propagated through shoes_canvas_send_wheel in canvas.c.

https://github.com/Shoes3/shoes3/blob/master/shoes/canvas.c#L2002
https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L201

The scrollbar is attached to the canvas->slot->vscroll

By the way, welcome to the team. You mentioned that scroll= is not in the manual. Never used it. Would you care to write an entry in the manual?

Collaborator

BackOrder commented Feb 8, 2015

Your results are similar to mine. @ccoupe and I talked a little about the implementation and it seems that the wheel events are properly propagated through shoes_canvas_send_wheel in canvas.c.

https://github.com/Shoes3/shoes3/blob/master/shoes/canvas.c#L2002
https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L201

The scrollbar is attached to the canvas->slot->vscroll

By the way, welcome to the team. You mentioned that scroll= is not in the manual. Never used it. Would you care to write an entry in the manual?

@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Feb 8, 2015

Contributor

Thanks for the offer !!! :-)))
ok for the entry in the manual, but i'll submit it to both of you before -english is not my mother tongue -

i have a superficial understanding of what's going on at that C deep level :-D

here's what i understood back in shoes level, just in case it gives a clue of what's going on deeper :
in the @s stack declaration inside timer(0) block @s.scroll_top and @s.scroll_max are not avalaible : @s.scroll_max equals to 0 and setting @s.scroll_top to whatever value has no effect !
later in a @s.start block info "@s.scroll_max = #{@s.scroll_max}" reports a correct value but setting @s.scroll_top still has no effect while info "@s.scroll_top = #{@s.scroll_top}" reports the correct value
i played with this :

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { 
            old_height = @s.height
            @s.height = @s.scroll_height 
            @s.scroll_top = @s.scroll_max
            info "@s.scroll_height = #{@s.scroll_height}"
            info "@s.scroll_max = #{@s.scroll_max}"
            @s.scroll_top = @s.scroll_height - old_height
            info "@s.scroll_top = #{@s.scroll_top}"
      }
    }
    @s.start { |me|
        info "me.scroll_max = #{me.scroll_max}"
        info "me.scroll_height = #{me.scroll_height}"
        info "me.scroll_top = #{me.scroll_top}"
        me.scroll_top = me.scroll_max
        info "me.scroll_top = #{me.scroll_top}"
    }
}
Contributor

passenger94 commented Feb 8, 2015

Thanks for the offer !!! :-)))
ok for the entry in the manual, but i'll submit it to both of you before -english is not my mother tongue -

i have a superficial understanding of what's going on at that C deep level :-D

here's what i understood back in shoes level, just in case it gives a clue of what's going on deeper :
in the @s stack declaration inside timer(0) block @s.scroll_top and @s.scroll_max are not avalaible : @s.scroll_max equals to 0 and setting @s.scroll_top to whatever value has no effect !
later in a @s.start block info "@s.scroll_max = #{@s.scroll_max}" reports a correct value but setting @s.scroll_top still has no effect while info "@s.scroll_top = #{@s.scroll_top}" reports the correct value
i played with this :

Shoes.app {
    @h = stack(:height => 100) { }
    @s = stack(:height => app.slot.height - 100, :scroll => true) {
        (0..100).each { |n| para "#{n}\n" }
        timer(0) { 
            old_height = @s.height
            @s.height = @s.scroll_height 
            @s.scroll_top = @s.scroll_max
            info "@s.scroll_height = #{@s.scroll_height}"
            info "@s.scroll_max = #{@s.scroll_max}"
            @s.scroll_top = @s.scroll_height - old_height
            info "@s.scroll_top = #{@s.scroll_top}"
      }
    }
    @s.start { |me|
        info "me.scroll_max = #{me.scroll_max}"
        info "me.scroll_height = #{me.scroll_height}"
        info "me.scroll_top = #{me.scroll_top}"
        me.scroll_top = me.scroll_max
        info "me.scroll_top = #{me.scroll_top}"
    }
}
@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Feb 8, 2015

Contributor

for the scroll= method : just copied/pasted from the :scroll style documentation :

=== scroll = true or false ===

Establishes this slot as a scrolling slot.  If `scroll = true` is set, the
slot will show a scrollbar if any of its contents go past its height.  The
scrollbar will appear and disappear as needed.

or just

see [[Styles.scroll]] style

btw in a smooth persnickety world shouldn't the getter method scroll be named scroll? instead

Contributor

passenger94 commented Feb 8, 2015

for the scroll= method : just copied/pasted from the :scroll style documentation :

=== scroll = true or false ===

Establishes this slot as a scrolling slot.  If `scroll = true` is set, the
slot will show a scrollbar if any of its contents go past its height.  The
scrollbar will appear and disappear as needed.

or just

see [[Styles.scroll]] style

btw in a smooth persnickety world shouldn't the getter method scroll be named scroll? instead

@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Feb 9, 2015

Collaborator

You did a good job on redacting scroll= method. I'd say you should add _See also [[Styles.scroll]] style._ at the end of the paragraph because it makes a good reference. Please, go ahead with committing your contribution. Don't forget to test the manual before committing.

btw in a smooth persnickety world shouldn't the getter method scroll be named scroll? instead

@ccoupe and I talked about the subject and it also been brought up in issue #14. Shoes DSL was never entirely thought through before being implemented giving place to some inconsistencies. Cecil is always reminding me that 3.2 is a maintenance release and thus compatibility matters. This might be in a hypothetical 3.3 version, if we ever get there. I would too appreciate consistency.

Cecil was alone making Shoes 3.2 possible for over a year. So such improvements were far fetched. Perhaps with your help, my help and Cecil... we might eventually see such changes.

You might be interested in the wish list page on https://github.com/Shoes3/shoes3/wiki/The-Future-of-Shoes.

Collaborator

BackOrder commented Feb 9, 2015

You did a good job on redacting scroll= method. I'd say you should add _See also [[Styles.scroll]] style._ at the end of the paragraph because it makes a good reference. Please, go ahead with committing your contribution. Don't forget to test the manual before committing.

btw in a smooth persnickety world shouldn't the getter method scroll be named scroll? instead

@ccoupe and I talked about the subject and it also been brought up in issue #14. Shoes DSL was never entirely thought through before being implemented giving place to some inconsistencies. Cecil is always reminding me that 3.2 is a maintenance release and thus compatibility matters. This might be in a hypothetical 3.3 version, if we ever get there. I would too appreciate consistency.

Cecil was alone making Shoes 3.2 possible for over a year. So such improvements were far fetched. Perhaps with your help, my help and Cecil... we might eventually see such changes.

You might be interested in the wish list page on https://github.com/Shoes3/shoes3/wiki/The-Future-of-Shoes.

@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Feb 24, 2015

Collaborator

Setting out a printf in gtk.c:shoes_app_gtk_wheel() demonstrated that it is never called on the scrollbar of the original Shoes sample code. Scrolling in the main window will call the function but not affect the scrollbar (not scrolling). Scrolling on the scrollbar will scroll but never call the function. Somehow the window and the scrollbar are not connected to each other. Any idea @ccoupe ?

https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L289

  printf("shoes_app_gtk_wheel: %d, %f, %f\n", wheel, event->x, event->y);
  shoes_app_wheel(app, wheel, event->x, event->y);
Shoes.app {
   stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
   }
}
Collaborator

BackOrder commented Feb 24, 2015

Setting out a printf in gtk.c:shoes_app_gtk_wheel() demonstrated that it is never called on the scrollbar of the original Shoes sample code. Scrolling in the main window will call the function but not affect the scrollbar (not scrolling). Scrolling on the scrollbar will scroll but never call the function. Somehow the window and the scrollbar are not connected to each other. Any idea @ccoupe ?

https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L289

  printf("shoes_app_gtk_wheel: %d, %f, %f\n", wheel, event->x, event->y);
  shoes_app_wheel(app, wheel, event->x, event->y);
Shoes.app {
   stack(:height => app.slot.height, :scroll => true) {
      (0..100).each { |n| para "#{n}\n" }
   }
}
@BackOrder

This comment has been minimized.

Show comment
Hide comment
@BackOrder

BackOrder Feb 25, 2015

Collaborator

shoes_slot_init defines a callback for "value-changed" event, which is only triggered when the scrollbar is actually clicked (on it or up/down button). Adding a "scroll-event" sort of work, as it is called back indeed, but either crash immediately or won't scroll. Basically, vscroll still seems disconnected from its window.

g_signal_connect(G_OBJECT(slot->vscroll), "value-changed", 
   G_CALLBACK(shoes_canvas_gtk_scroll), (gpointer)c);

https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L944

Collaborator

BackOrder commented Feb 25, 2015

shoes_slot_init defines a callback for "value-changed" event, which is only triggered when the scrollbar is actually clicked (on it or up/down button). Adding a "scroll-event" sort of work, as it is called back indeed, but either crash immediately or won't scroll. Basically, vscroll still seems disconnected from its window.

g_signal_connect(G_OBJECT(slot->vscroll), "value-changed", 
   G_CALLBACK(shoes_canvas_gtk_scroll), (gpointer)c);

https://github.com/Shoes3/shoes3/blob/master/shoes/native/gtk.c#L944

passenger94 added a commit to passenger94/shoes3 that referenced this issue Apr 4, 2015

@passenger94

This comment has been minimized.

Show comment
Hide comment
@passenger94

passenger94 Apr 4, 2015

Contributor

working for me !!
canvas.c, app.c, in gtk.c relevant change is here :
https://github.com/passenger94/shoes3/blob/master/shoes/native/gtk.c#L1053

your first example and this one too :

Shoes.app do
   stack(:height => app.slot.height, :scroll => true, width: 200) {
      (0..100).each { |n| para "#{n}\n" }
   }
end
Contributor

passenger94 commented Apr 4, 2015

working for me !!
canvas.c, app.c, in gtk.c relevant change is here :
https://github.com/passenger94/shoes3/blob/master/shoes/native/gtk.c#L1053

your first example and this one too :

Shoes.app do
   stack(:height => app.slot.height, :scroll => true, width: 200) {
      (0..100).each { |n| para "#{n}\n" }
   }
end

@passenger94 passenger94 closed this Apr 4, 2015

@ccoupe ccoupe added this to the 3.2.23 milestone Apr 5, 2015

ccoupe added a commit that referenced this issue Jul 3, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment