Guys,
Looks like you have most of the details right.
Here's what I did for static re-initialization. (Figure 1A & 1B) Certainly I
must have missed some things. For one, I'm not especially thrilled with how I
hacked Fl_Surface_Device and Fl_Display_Device with set() functions, not how
the Fl_GDI_Graphics_Driver initialization takes place. Since these are
globals, doing reinitialization appears to be dicey.
Regarding Adobe's SDK. It is a C-based API. Adobe told me a few years ago
(CS4?) that they stopped unloading plug-ins between executions for performance.
On the Mac that started with CS5 and their Cocoa implementation, but on the PC
I think it happened earlier. I notice that dynamic linking happens upon
startup in CS5 (spotted this with a variant that used FLTKDLL.DLL instead).
I'm being called with the primary Photoshop thread and need to yield to
Photoshop if I'm doing heavy processing via a callback to push the progress bar
and test for the escape key. This permits events to be checked/handled by
Photoshop. Otherwise, my DLL is in charge.
As far as FLTKDLL.DLL testing, I have tried fully unloading the DLL (looping
until there is no more reference to it) and then reloading it again. This
should have had the effect of reinitialization, but the failure the second time
persisted. That led me down a path of wondering what happens in the OLE/COM
world.
My so-called "popup function" could as simple as Figure 2. (Hello World) and it
still fails the second time. Actually ->show() fails. The dialog never
appears yet we seem to be stuck in the event loop. The loop used to be
Fl::run(), but I read some conflicting stuff about multiple windows and thought
this would be better. Also notice the Fl::flush() calls. They made no
difference. This fits with Greg's conclusions about the event handling being
screwed up. I made an additional test by removing the event loop and instead
just doing a show/hide combination, and the ->show() call the second time does
not happen. Execution continues beyond that line (I assume ->show() is just
some kind of event post), but no dialog appears. ->shown() is true, though.
I've gotten approval from the bosses to attempt a two-part plug-in -- first
part that grabs the image, second part that does the processing/UI. Now I have
to do it. Doing it as a DLL is no biggie -- I've got a lot of experience with
that, but making part be stand-alone in a different process, and yet not appear
to be that way will be challenging. Especially that yield portion (I'd have to
go async between the two parts so that the Photoshop stub continues to allow
Photoshop to update). This gets ugly fast.
So here are my questions:
a) Why does FLTK rely upon exit() on the way out?
b) Does anyone have an idea about how to "save the state" of the GDI, event
handlers, and OpenGL so it could be easily restored? This might be the other
kind of solution.
c) Besides those in Fl_Devices.h, how many other classes have a persistent
static instantiation?
Also, I have absolutely no objections to contributing to the cause. I'm pretty
sure that someone else should be testing and checking in any changes that are
worthwhile keeping, though. :)
-Chris
-------------------------
Figure 1A: (from Fl.cxx)
#ifdef WIN32
///////////////INITIALIZE ALL OF FLTK WIN32 STATICS///////////////
//__Fl_Reinit (calls __Fl_win32_Reinit() in FL.cxx)
void __Fl_Reinit(void)
{
__Fl_win32_Reinit(); //Fl_win32.cxx
win32_at_exit.~Fl_Win32_At_Exit();
OleInitialize(0L);
handlers = 0;
dnd_flag = 0;
num_dwidgets = 0;
alloc_dwidgets = 0;
dwidgets = 0;
widget_watch = 0;
num_widget_watch = 0;
max_widget_watch = 0;
}//__Fl_Reinit
#endif
Figure 1B: (from Fl_win32.cxx)
///////////////INITIALIZE ALL OF FLTK WIN32 STATICS///////////////
//__Fl_win32_Reinit (called by __Fl_Reinit() in FL.cxx)
void __Fl_win32_Reinit(void)
{
static Fl_GDI_Graphics_Driver l_fl_gdi_driver;
static Fl_Display_Device l_fl_gdi_display(&l_fl_gdi_driver);
fl_gdi_driver = l_fl_gdi_driver;
fl_gdi_display = l_fl_gdi_display;
fl_graphics_driver = &l_fl_gdi_driver;
//fl_gdi_display(&fl_gdi_driver); //<-- ALWAYS FAILS TO COMPILE
$$$
//fl_graphics_driver = (Fl_Graphics_Driver*)&fl_gdi_driver; // the
current target driver of graphics operations
//Fl_Surface_Device::_surface = (Fl_Surface_Device*)&fl_gdi_display; //
the current target surface of graphics operations
//Fl_Display_Device::_display = &fl_gdi_display; // the platform display
Fl_Surface_Device::set_surface(&fl_gdi_display); // the current target
surface of graphics operations
Fl_Display_Device::set_display(&fl_gdi_display); // the platform display
s_wsock_mod = 0;
fl_wsk_select_f s_wsock_select = 0;
fl_wsk_fd_is_set_f fl_wsk_fd_is_set = 0;
s_imm_module = 0;
flTypeImmGetContext flImmGetContext = 0;
flTypeImmSetCompositionWindow flImmSetCompositionWindow = 0;
flTypeImmReleaseContext flImmReleaseContext = 0;
flTypeImmIsIME flImmIsIME = 0;
maxfd = 0;
nfds = 0;
fd_array_size = 0;
fl_aimm = NULL;
fl_is_ime = 0;
//I suspect these are the problem:
fl_gc = 0;
fl_window = NULL;
win_DC_list = 0;
}//__Fl_Reinit_FLTK
Figure 1C: (from Fl_Device.H)
/////////ADDED 8/30/12 - Fl_Surface_Device
static inline void set_surface(Fl_Surface_Device *a) {_surface = a;};
/////////ADDED 8/30/12 - Fl_Display_Device
static inline void set_display(Fl_Display_Device *a) {_display = a;};
Figure 2: (Error Message dialog, based upon Hello World)
static char __message[256];
static char __title[256];
int ErrorMessage(const char *title, const char *message)
{
strcpy(__title, title);
strcpy(__message, message);
Fl_Window *window = new Fl_Window(40,100,340,180, __title);
window->set_modal();
Fl_Box *box = new Fl_Box(0,0,340,180,__message);
box->box(FL_UP_BOX);
box->labelsize(24);
window->end();
window->show(0, NULL); //doesn't appear to actually
show the second time.
Fl::flush(); //allow dialog to appear prior
to event loop?
while(window->visible()) //functionally an infinite loop
the second time.
Fl::wait();
Fl::flush(); //never gets here the second
time
return 0;
}//ErrorMessage
> Chris et al,
>
> Can I just summarise what I *think* is being done here, to make sure I actu=
> ally understand the question?
>
> So...
>
> - I imagine that PS calls a function with a C API (and perhaps provides e.g=
> .. callbacks, also with C API, to allow the called function to interact with=
> the PS instance.)
>
> - The called function is used to pop-up some GUI written in fltk, which I a=
> ssume calls Fl::run();
>
> - When the pop-up closes, the function returns to PS.
>
>
> Observed behaviours are...
>
> - The first time this is invoked, the pop-up appears just fine and it all J=
> ust Works.
>
> - On subsequent attempts, the GUI simply never appears...
>
>
> We think that...
>
> - PS does not unload the fltk DLL after the first pass
>
> - Attempts to unload the DLL on purpose don't seem to help
>
> - The OP (Chris) has made some attempts to "reset" the fltk static context =
> between runs, but that doesn't seem to have helped
>
> - Other stuff...?
>
>
> Looking at Fl.cxx, I wondered about:
>
> - the "Check" list (near line 342) - can we (should we? do we?) reset that =
> between runs of the pop-up?
>
> - the oleInitialized stuff, and win32_at_exit instance - can we (should we)=
> trigger that manually when the pop-up expires to get things ready for the =
> next time?
>
> - Fl_X::first (near line 657) do we need to clean that up...?
>
>
>
> Also: What does the Chris do in the pop-up function? =
>
>
> I imagine that the first time in, this creates all the fltk windows and wid=
> gets that are needed.
>
> Now, does it tear them down on pop-up exit, then re-create them on the next=
> call?
>
> Or, should it create them on the first call, but retain them and re-use the=
> m on subsequent calls? Would that be better? Would that perhaps avoid the r=
> e-init issues we seem to be seeing?
>
>
> Thoughts?
>
>
>
> SELEX Galileo Ltd
> Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS=
> 14 3EL
> A company registered in England & Wales. Company no. 02426132
> ********************************************************************
> This email and any attachments are confidential to the intended
> recipient and may also be privileged. If you are not the intended
> recipient please delete it from your system and notify the sender.
> You should not copy it or use it for any purpose nor disclose or
> distribute its contents to any other person.
> ********************************************************************
>
_______________________________________________
fltk mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk