RFC: using Fl_Printer in longer operations

17 views
Skip to first unread message

melcher....@googlemail.com

unread,
Jun 12, 2022, 7:40:40 AM6/12/22
to fltk.coredev
I added a comment yesterday: https://github.com/fltk/fltk/commit/bcbdf5546f53afdc0e3a4bb7458eb863783e76fd

and it's probably not the best solution.

When a print operation takes longer for whatever reason, and some other FL graphics may be rendered between a begin_page() and end_page() - a progress dialog, for example - the progress dialog rendering is sent to the printer not the screen.

I know that this is a very uncommon case, so I would like to ask the core devs how to solve this:
 a: ignore, probably nobody (besides me) will ever have this issue
 b: keep the doc changes to first pop the printer context, then push the context
 c: change docs to first push the screen context, then render on screen, then pop back to the printer context
 d: add a suspend() and resume() method that does b: or c: (which one)

Example:
  myPrinter->begin_page();
  while (!done) {
    draw_part_of_page(); // slow operation
    Fl::wait(0); // keep the app responsive, also flushes drawing requests
  }
  myPrinter->end_page();

So d: would add myPrinter->suspend() before , and myPrinter->resume() after the Fl::wait(0) statement.

imacarthur

unread,
Jun 12, 2022, 2:26:21 PM6/12/22
to fltk.coredev
I've never actually hit this, but I can see the point. As a solution for this case, option (d) seems sensible to me as it makes the operation explicit.
How suspend() and resume() should operate, in terms of popping/pushing the printer context and/or the screen context I do not know - I have no intuition about how that would best be achieved. 
I guess Manolo is best placed for that call?

Albrecht Schlosser

unread,
Jun 13, 2022, 12:23:56 PM6/13/22
to fltkc...@googlegroups.com
I see your points but why do we need another method? In the context
given above I would really do something equivalent to suspend/resume
before and after Fl::wait(0) but this can likely be done with existing
methods as Manolo suggested in the respective commit comment (unless I'm
missing something).

As Manolo wrote, adding
Fl_Surface_Device::push_current(Fl_Display_Device::display_device());
before Fl::wait(); and
  Fl_Surface_Device::pop_current();
after Fl::wait(); would work.

The drawback would be that you would push another context on the stack
rather than popping first to go back to the previous context and return
to the printer context after Fl::wait().

So, to answer the "other" question: if we added such new methods I'd
suggest to `pop` the drawing context in `suspend()` and `push` the
printer context in `resume()`. This would make these methods independent
of the "previous" context - which would  be very likely but not
necessarily the "display" context.

I have no idea how to implement such a `resume()` method that would push
the pre-existing printer context back on the stack but I guess Manolo
would know?

melcher....@googlemail.com

unread,
Jun 13, 2022, 1:16:42 PM6/13/22
to fltk.coredev

Implementing resume() is easy as it is a method of the printer class. Both functions are one-liners that will be inlined by the compiler, so they really only are a shortcut in the header.

I am still torn if it should be push(screen)/pop() or pop()/push(printer). If the pushed context is a another surface, the second solution would be wrong. So 
Fl_Printer::suspend() { Fl_Surface_Device::push_current(Fl_Display_Device::display_device());  }
Fl_Printer::resume() { Fl_Surface_Device::pop_current(); }
are a good solution IMHO to hide the surface handling if a user absolutely must call Fl::wait() for some reason.

So, yes, that would be Manolo's suggestion.

Thanks all for looking into this!
 
Albrecht Schlosser schrieb am Montag, 13. Juni 2022 um 18:23:56 UTC+2:
On 6/12/22 13:40 'melcher....@...' via fltk.coredev wrote:
As Manolo wrote, adding
Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); 
before Fl::wait(); and
  Fl_Surface_Device::pop_current();
after Fl::wait(); would work.
  
So, to answer the "other" question: if we added such new methods I'd

Albrecht Schlosser

unread,
Jun 13, 2022, 4:52:28 PM6/13/22
to fltkc...@googlegroups.com
On 6/13/22 19:16 'melcher....@googlemail.com' via fltk.coredev wrote:

Implementing resume() is easy as it is a method of the printer class. Both functions are one-liners that will be inlined by the compiler, so they really only are a shortcut in the header.

I am still torn if it should be push(screen)/pop() or pop()/push(printer). If the pushed context is a another surface, the second solution would be wrong.

That depends on the definition of right or wrong or, to be clear, the definition of the method. In my mind suspend() would return to the state before the printing began (i.e. pop()) and the following resume(), i.e. push() would switch back to the printer context.

What you suppose - i.e. first push(screen) - would unconditionally push the screen context as the active surface which is exactly what you need, as you describe it, but this would not be a general solution IMHO.


So 
Fl_Printer::suspend() { Fl_Surface_Device::push_current(Fl_Display_Device::display_device());  }
Fl_Printer::resume() { Fl_Surface_Device::pop_current(); }
are a good solution IMHO to hide the surface handling if a user absolutely must call Fl::wait() for some reason.

So, yes, that would be Manolo's suggestion.

I'm not convinced that this is the best solution though. IMHO suspend() should definitely *return* to the previous condition before printing started and not add yet another context to the stack.

When the user calls Fl_Printer::suspend() we must (and can) assume that the printer context is active and Fl_Printer::resume() can always push() the printer context and thus make it active.

What I want to say is that suspend means in my understanding to return to the previous state and not to switch to a new state. If we used a different method instead of Fl_Printer::suspend(), maybe Fl_Surface_Device::push_display() that would be clear, and a following Fl_Surface_Device::pop_current() would resume printing.

It's difficult to express why I think that "suspend" should not "push the display" context. I hope you get it. Somehow.

BTW: Matt, what you try to do would work with either way, so this is not the problem.


Thanks all for looking into this!
 
Albrecht Schlosser schrieb am Montag, 13. Juni 2022 um 18:23:56 UTC+2:
On 6/12/22 13:40 'melcher....@...' via fltk.coredev wrote:
As Manolo wrote, adding
Fl_Surface_Device::push_current(Fl_Display_Device::display_device()); 
before Fl::wait(); and
  Fl_Surface_Device::pop_current();
after Fl::wait(); would work.
  
So, to answer the "other" question: if we added such new methods I'd
suggest to `pop` the drawing context in `suspend()` and `push` the
printer context in `resume()`. This would make these methods independent
of the "previous" context - which would  be very likely but not
necessarily the "display" context.

I have no idea how to implement such a `resume()` method that would push
the pre-existing printer context back on the stack but I guess Manolo
would know?


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/8100ce56-1e09-472f-bde5-9bb4ea5f81a4n%40googlegroups.com.

Manolo

unread,
Jun 14, 2022, 1:00:15 AM6/14/22
to fltk.coredev
If they are created, the new suspend() and resume() methods would go to class Fl_Paged_Device, not class Fl_Printer.

I agree the name Fl_Paged_Device::suspend() suggests to return to the device context at work before Fl_Paged_Device::begin_page(), so should correspond to pop.

But the need for new methods seems totally moot for me since existing one-line calls are enough:
Fl_Surface_Device::push_current(Fl_Display_Device::display_device());
…… refresh the GUI or other display-using tasks ……
Fl_Surface_Device::pop_current();
Reply all
Reply to author
Forward
0 new messages