mozilla: don't hold any reference to root object to prevent ownership issues on...
[vlc.git] / mozilla / vlcshell.cpp
1 /*****************************************************************************
2  * vlcshell.cpp: a VLC plugin for Mozilla
3  *****************************************************************************
4  * Copyright (C) 2002-2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include "config.h"
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32
33 /* Mozilla stuff */
34 #ifdef HAVE_MOZILLA_CONFIG_H
35 #   include <mozilla-config.h>
36 #endif
37
38 /* This is from mozilla java, do we really need it? */
39 #if 0
40 #include <jri.h>
41 #endif
42
43 #include "vlcplugin.h"
44
45 /* Enable/disable debugging printf's for X11 resizing */
46 #undef X11_RESIZE_DEBUG
47
48 #define WINDOW_TEXT "(no video)"
49
50 /*****************************************************************************
51  * Unix-only declarations
52 ******************************************************************************/
53 #ifdef XP_UNIX
54
55 static void Redraw( Widget w, XtPointer closure, XEvent *event );
56 static void Resize( Widget w, XtPointer closure, XEvent *event );
57
58 #endif
59
60 /*****************************************************************************
61  * MacOS-only declarations
62 ******************************************************************************/
63 #ifdef XP_MACOSX
64 #endif
65
66 /*****************************************************************************
67  * Windows-only declarations
68  *****************************************************************************/
69 #ifdef XP_WIN
70
71 static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar );
72
73 #endif
74
75 /******************************************************************************
76  * UNIX-only API calls
77  *****************************************************************************/
78 char * NPP_GetMIMEDescription( void )
79 {
80     return PLUGIN_MIMETYPES;
81 }
82
83 NPError NPP_GetValue( NPP instance, NPPVariable variable, void *value )
84 {
85
86     static char psz_desc[1000];
87
88     /* plugin class variables */
89     switch( variable )
90     {
91         case NPPVpluginNameString:
92             *((char **)value) = PLUGIN_NAME;
93             return NPERR_NO_ERROR;
94
95         case NPPVpluginDescriptionString:
96             snprintf( psz_desc, sizeof(psz_desc), PLUGIN_DESCRIPTION, VLC_Version() );
97             *((char **)value) = psz_desc;
98             return NPERR_NO_ERROR;
99
100         default:
101             /* move on to instance variables ... */
102             ;
103     }
104
105     if( instance == NULL )
106     {
107         return NPERR_INVALID_INSTANCE_ERROR;
108     }
109
110     /* plugin instance variables */
111
112     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
113     if( NULL == p_plugin )
114     {
115         // plugin has not been initialized yet !
116         return NPERR_INVALID_INSTANCE_ERROR;
117     }
118
119     switch( variable )
120     {
121         case NPPVpluginScriptableNPObject:
122             /* retrieve plugin root class */
123             NPClass *scriptClass = p_plugin->getScriptClass();
124             if( scriptClass )
125             {
126                 /* create an instance and return it */
127                 *(NPObject**)value = NPN_CreateObject(instance, scriptClass);
128                 return NPERR_NO_ERROR;
129             }
130             break;
131
132         default:
133             ;
134     }
135     return NPERR_GENERIC_ERROR;
136 }
137
138 /*
139  * there is some confusion in gecko headers regarding definition of this API
140  * NPPVariable is wrongly defined as NPNVariable, which sounds incorrect.
141  */
142
143 NPError NPP_SetValue( NPP instance, NPNVariable variable, void *value )
144 {
145     return NPERR_GENERIC_ERROR;
146 }
147
148 /******************************************************************************
149  * Mac-only API calls
150  *****************************************************************************/
151 #ifdef XP_MACOSX
152 int16 NPP_HandleEvent( NPP instance, void * event )
153 {
154     static UInt32 lastMouseUp = 0;
155
156     if( instance == NULL )
157     {
158         return false;
159     }
160
161     VlcPlugin *p_plugin = (VlcPlugin*)instance->pdata;
162
163     if( p_plugin == NULL )
164     {
165         return false;
166     }
167
168     EventRecord *myEvent = (EventRecord*)event;
169
170     switch( myEvent->what )
171     {
172         case nullEvent:
173             break;
174         case mouseDown:
175         {
176             if( (myEvent->when - lastMouseUp) < GetDblTime() )
177             {
178                 /* double click */
179                 libvlc_instance_t *p_vlc = p_plugin->getVLC();
180
181                 if( p_vlc )
182                 {
183                     if( libvlc_playlist_isplaying(p_vlc, NULL) )
184                     {
185                         libvlc_input_t *p_input = libvlc_playlist_get_input(p_vlc, NULL);
186                         if( p_input )
187                         {
188                             libvlc_toggle_fullscreen(p_input, NULL);
189                             libvlc_input_free(p_input);
190                         }
191                     }
192                 }
193             }
194             return true;
195         }
196         case mouseUp:
197             lastMouseUp = myEvent->when;
198             return true;
199         case keyUp:
200         case keyDown:
201         case autoKey:
202             return true;
203         case updateEvt:
204         {
205             int needsDisplay = TRUE;
206             libvlc_instance_t *p_vlc = p_plugin->getVLC();
207
208             if( p_vlc )
209             {
210                 if( libvlc_playlist_isplaying(p_vlc, NULL) )
211                 {
212                     libvlc_input_t *p_input = libvlc_playlist_get_input(p_vlc, NULL);
213                     if( p_input )
214                     {
215                         needsDisplay = ! libvlc_input_has_vout(p_input, NULL);
216                         libvlc_input_free(p_input);
217                     }
218                 }
219             }
220
221             const NPWindow *npwindow = p_plugin->getWindow();
222
223             if( needsDisplay && npwindow->window )
224             {
225                 /* draw the beautiful "No Picture" */
226
227                 ForeColor(blackColor);
228                 PenMode( patCopy );
229
230                 /* seems that firefox forgets to set the following on occasion (reload) */
231                 SetOrigin(((NP_Port *)npwindow->window)->portx, ((NP_Port *)npwindow->window)->porty);
232
233                 Rect rect;
234                 rect.left = 0;
235                 rect.top = 0;
236                 rect.right = npwindow->width;
237                 rect.bottom = npwindow->height;
238                 PaintRect( &rect );
239
240                 ForeColor(whiteColor);
241                 MoveTo( (npwindow->width-80)/ 2  , npwindow->height / 2 );
242                 DrawText( WINDOW_TEXT , 0 , strlen(WINDOW_TEXT) );
243             }
244             return true;
245         }
246         case activateEvt:
247             return false;
248         case NPEventType_GetFocusEvent:
249         case NPEventType_LoseFocusEvent:
250             return true;
251         case NPEventType_AdjustCursorEvent:
252             return false;
253         case NPEventType_MenuCommandEvent:
254             return false;
255         case NPEventType_ClippingChangedEvent:
256             return false;
257         case NPEventType_ScrollingBeginsEvent:
258         case NPEventType_ScrollingEndsEvent:
259             return true;
260         default:
261             ;
262     }
263     return false;
264 }
265 #endif /* XP_MACOSX */
266
267 /******************************************************************************
268  * General Plug-in Calls
269  *****************************************************************************/
270 NPError NPP_Initialize( void )
271 {
272     return NPERR_NO_ERROR;
273 }
274
275 jref NPP_GetJavaClass( void )
276 {
277     return NULL;
278 }
279
280 void NPP_Shutdown( void )
281 {
282     ;
283 }
284
285 NPError NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
286                  char* argn[], char* argv[], NPSavedData* saved )
287 {
288     NPError status;
289
290     if( instance == NULL )
291     {
292         return NPERR_INVALID_INSTANCE_ERROR;
293     }
294
295     VlcPlugin * p_plugin = new VlcPlugin( instance, mode );
296     if( NULL == p_plugin )
297     {
298         return NPERR_OUT_OF_MEMORY_ERROR;
299     }
300
301     status = p_plugin->init(argc, argn, argv);
302     if( NPERR_NO_ERROR == status )
303     {
304         instance->pdata = reinterpret_cast<void*>(p_plugin);
305         //NPN_SetValue(instance, NPPVpluginWindowBool, (void *)false);
306         NPN_SetValue(instance, NPPVpluginTransparentBool, (void *)false);
307     }
308     else
309     {
310         delete p_plugin;
311     }
312     return status;
313 }
314
315 NPError NPP_Destroy( NPP instance, NPSavedData** save )
316 {
317     if( NULL == instance )
318         return NPERR_INVALID_INSTANCE_ERROR;
319
320     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
321     if( NULL == p_plugin )
322         return NPERR_NO_ERROR;
323
324     instance->pdata = NULL;
325
326 #if XP_WIN
327     HWND win = (HWND)p_plugin->getWindow()->window;
328     WNDPROC winproc = p_plugin->getWindowProc();
329     if( winproc )
330     {
331         /* reset WNDPROC */
332         SetWindowLong( win, GWL_WNDPROC, (LONG)winproc );
333     }
334 #endif
335
336     delete p_plugin;
337
338     return NPERR_NO_ERROR;
339 }
340
341 NPError NPP_SetWindow( NPP instance, NPWindow* window )
342 {
343     if( ! instance )
344     {
345         return NPERR_INVALID_INSTANCE_ERROR;
346     }
347
348     /* NPP_SetWindow may be called before NPP_New (Opera) */
349     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(instance->pdata);
350     if( ! p_plugin )
351     {
352         /* we should probably show a splash screen here */
353         return NPERR_NO_ERROR;
354     }
355
356     libvlc_instance_t *p_vlc = p_plugin->getVLC();
357
358     /*
359      * PLUGIN DEVELOPERS:
360      *  Before setting window to point to the
361      *  new window, you may wish to compare the new window
362      *  info to the previous window (if any) to note window
363      *  size changes, etc.
364      */
365
366     const NPWindow *curwin = p_plugin->getWindow();
367
368 #ifdef XP_MACOSX
369     if( window && window->window )
370     {
371         /* check if plugin has a new parent window */
372         CGrafPtr drawable = (((NP_Port*) (window->window))->port);
373         if( !curwin->window || drawable != (((NP_Port*) (curwin->window))->port) )
374         {
375             /* set/change parent window */
376             libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
377         }
378
379         /* as MacOS X video output is windowless, set viewport */
380         libvlc_rectangle_t view, clip;
381
382         /*
383         ** browser sets port origin to top-left location of plugin relative to GrafPort
384         ** window origin is set relative to document, which of little use for drawing
385         */
386         view.top     = ((NP_Port*) (window->window))->porty;
387         view.left    = ((NP_Port*) (window->window))->portx;
388         view.bottom  = window->height+view.top;
389         view.right   = window->width+view.left;
390         /* clipRect coordinates are also relative to GrafPort */
391         clip.top     = window->clipRect.top;
392         clip.left    = window->clipRect.left;
393         clip.bottom  = window->clipRect.bottom;
394         clip.right   = window->clipRect.right;
395
396         libvlc_video_set_viewport(p_vlc, &view, &clip, NULL);
397
398         /* remember window details */
399         p_plugin->setWindow(window);
400     }
401 #endif /* XP_MACOSX */
402
403 #ifdef XP_WIN
404     if( window && window->window )
405     {
406         /* check if plugin has a new parent window */
407         HWND drawable = (HWND) (window->window);
408         if( !curwin->window || drawable != curwin->window )
409         {
410             /* reset previous window settings */
411             HWND oldwin = (HWND)p_plugin->getWindow()->window;
412             WNDPROC oldproc = p_plugin->getWindowProc();
413             if( oldproc )
414             {
415                 /* reset WNDPROC */
416                 SetWindowLong( oldwin, GWL_WNDPROC, (LONG)oldproc );
417             }
418             /* attach our plugin object */
419             SetWindowLongPtr((HWND)drawable, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(p_plugin));
420
421             /* install our WNDPROC */
422             p_plugin->setWindowProc( (WNDPROC)SetWindowLong( drawable,
423                                                            GWL_WNDPROC, (LONG)Manage ) );
424
425             /* change window style to our liking */
426             LONG style = GetWindowLong((HWND)drawable, GWL_STYLE);
427             style |= WS_CLIPCHILDREN|WS_CLIPSIBLINGS;
428             SetWindowLong((HWND)drawable, GWL_STYLE, style);
429
430             /* change/set parent */
431             libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
432         }
433
434         /* remember window details */
435         p_plugin->setWindow(window);
436
437         /* Redraw window */
438         InvalidateRect( (HWND)drawable, NULL, TRUE );
439         UpdateWindow( (HWND)drawable );
440     }
441     else
442     {
443         /* reset WNDPROC */
444         HWND oldwin = (HWND)curwin->window;
445         SetWindowLong( oldwin, GWL_WNDPROC, (LONG)(p_plugin->getWindowProc()) );
446         p_plugin->setWindowProc(NULL);
447         /* change/set parent */
448         libvlc_video_set_parent(p_vlc, 0, NULL);
449     }
450 #endif /* XP_WIN */
451
452 #ifdef XP_UNIX
453     if( window && window->window )
454     {
455         Window  drawable   = (Window) window->window;
456         if( !curwin->window || drawable != (Window)curwin->window )
457         {
458             Display *p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
459
460             XResizeWindow( p_display, drawable, window->width, window->height );
461             Widget w = XtWindowToWidget( p_display, drawable );
462
463             XtAddEventHandler( w, ExposureMask, FALSE, (XtEventHandler)Redraw, p_plugin );
464             XtAddEventHandler( w, StructureNotifyMask, FALSE, (XtEventHandler)Resize, p_plugin );
465
466             /* set/change parent window */
467             libvlc_video_set_parent(p_vlc, (libvlc_drawable_t)drawable, NULL);
468
469             /* remember window */
470             p_plugin->setWindow(window);
471
472             Redraw( w, (XtPointer)p_plugin, NULL );
473         }
474     }
475 #endif /* XP_UNIX */
476
477     if( !p_plugin->b_stream )
478     {
479         if( p_plugin->psz_target )
480         {
481             if( libvlc_playlist_add( p_vlc, p_plugin->psz_target, NULL, NULL ) != -1 )
482             {
483                 if( p_plugin->b_autoplay )
484                 {
485                     libvlc_playlist_play(p_vlc, 0, 0, NULL, NULL);
486                 }
487             }
488             p_plugin->b_stream = VLC_TRUE;
489         }
490     }
491     return NPERR_NO_ERROR;
492 }
493
494 NPError NPP_NewStream( NPP instance, NPMIMEType type, NPStream *stream,
495                        NPBool seekable, uint16 *stype )
496 {
497     if( NULL == instance  )
498     {
499         return NPERR_INVALID_INSTANCE_ERROR;
500     }
501
502     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
503     if( NULL == p_plugin )
504     {
505         return NPERR_INVALID_INSTANCE_ERROR;
506     }
507
508    /*
509    ** Firefox/Mozilla may decide to open a stream from the URL specified
510    ** in the SRC parameter of the EMBED tag and pass it to us
511    **
512    ** since VLC will open the SRC URL as well, we're not interested in
513    ** that stream. Otherwise, we'll take it and queue it up in the playlist
514    */
515     if( !p_plugin->psz_target || strcmp(stream->url, p_plugin->psz_target) )
516     {
517         /* TODO: use pipes !!!! */
518         *stype = NP_ASFILEONLY;
519         return NPERR_NO_ERROR;
520     }
521     return NPERR_GENERIC_ERROR;
522 }
523
524 int32 NPP_WriteReady( NPP instance, NPStream *stream )
525 {
526     /* TODO */
527     return 8*1024;
528 }
529
530
531 int32 NPP_Write( NPP instance, NPStream *stream, int32 offset,
532                  int32 len, void *buffer )
533 {
534     /* TODO */
535     return len;
536 }
537
538
539 NPError NPP_DestroyStream( NPP instance, NPStream *stream, NPError reason )
540 {
541     if( instance == NULL )
542     {
543         return NPERR_INVALID_INSTANCE_ERROR;
544     }
545     return NPERR_NO_ERROR;
546 }
547
548
549 void NPP_StreamAsFile( NPP instance, NPStream *stream, const char* fname )
550 {
551     if( instance == NULL )
552     {
553         return;
554     }
555
556     VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(instance->pdata);
557     if( NULL == p_plugin )
558     {
559         return;
560     }
561
562     if( libvlc_playlist_add( p_plugin->getVLC(), fname, stream->url, NULL ) != -1 )
563     {
564         if( p_plugin->b_autoplay )
565         {
566             libvlc_playlist_play( p_plugin->getVLC(), 0, 0, NULL, NULL);
567         }
568     }
569 }
570
571
572 void NPP_URLNotify( NPP instance, const char* url,
573                     NPReason reason, void* notifyData )
574 {
575     /***** Insert NPP_URLNotify code here *****\
576     PluginInstance* p_plugin;
577     if (instance != NULL)
578         p_plugin = (PluginInstance*) instance->pdata;
579     \*********************************************/
580 }
581
582
583 void NPP_Print( NPP instance, NPPrint* printInfo )
584 {
585     if( printInfo == NULL )
586     {
587         return;
588     }
589
590     if( instance != NULL )
591     {
592         /***** Insert NPP_Print code here *****\
593         PluginInstance* p_plugin = (PluginInstance*) instance->pdata;
594         \**************************************/
595
596         if( printInfo->mode == NP_FULL )
597         {
598             /*
599              * PLUGIN DEVELOPERS:
600              *  If your plugin would like to take over
601              *  printing completely when it is in full-screen mode,
602              *  set printInfo->pluginPrinted to TRUE and print your
603              *  plugin as you see fit.  If your plugin wants Netscape
604              *  to handle printing in this case, set
605              *  printInfo->pluginPrinted to FALSE (the default) and
606              *  do nothing.  If you do want to handle printing
607              *  yourself, printOne is true if the print button
608              *  (as opposed to the print menu) was clicked.
609              *  On the Macintosh, platformPrint is a THPrint; on
610              *  Windows, platformPrint is a structure
611              *  (defined in npapi.h) containing the printer name, port,
612              *  etc.
613              */
614
615             /***** Insert NPP_Print code here *****\
616             void* platformPrint =
617                 printInfo->print.fullPrint.platformPrint;
618             NPBool printOne =
619                 printInfo->print.fullPrint.printOne;
620             \**************************************/
621
622             /* Do the default*/
623             printInfo->print.fullPrint.pluginPrinted = FALSE;
624         }
625         else
626         {
627             /* If not fullscreen, we must be embedded */
628             /*
629              * PLUGIN DEVELOPERS:
630              *  If your plugin is embedded, or is full-screen
631              *  but you returned false in pluginPrinted above, NPP_Print
632              *  will be called with mode == NP_EMBED.  The NPWindow
633              *  in the printInfo gives the location and dimensions of
634              *  the embedded plugin on the printed page.  On the
635              *  Macintosh, platformPrint is the printer port; on
636              *  Windows, platformPrint is the handle to the printing
637              *  device context.
638              */
639
640             /***** Insert NPP_Print code here *****\
641             NPWindow* printWindow =
642                 &(printInfo->print.embedPrint.window);
643             void* platformPrint =
644                 printInfo->print.embedPrint.platformPrint;
645             \**************************************/
646         }
647     }
648 }
649
650 /******************************************************************************
651  * Windows-only methods
652  *****************************************************************************/
653 #if XP_WIN
654 static LRESULT CALLBACK Manage( HWND p_hwnd, UINT i_msg, WPARAM wpar, LPARAM lpar )
655 {
656     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(GetWindowLongPtr(p_hwnd, GWLP_USERDATA));
657
658     switch( i_msg )
659     {
660         case WM_ERASEBKGND:
661             return 1L;
662
663         case WM_PAINT:
664         {
665             PAINTSTRUCT paintstruct;
666             HDC hdc;
667             RECT rect;
668
669             hdc = BeginPaint( p_hwnd, &paintstruct );
670
671             GetClientRect( p_hwnd, &rect );
672
673             FillRect( hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH) );
674             SetTextColor(hdc, RGB(255, 255, 255));
675             SetBkColor(hdc, RGB(0, 0, 0));
676             DrawText( hdc, WINDOW_TEXT, strlen(WINDOW_TEXT), &rect, DT_CENTER|DT_VCENTER|DT_SINGLELINE); 
677
678             EndPaint( p_hwnd, &paintstruct );
679             return 0L;
680         }
681         default:
682             /* delegate to default handler */
683             return p_plugin->getWindowProc()( p_hwnd, i_msg, wpar, lpar );
684     }
685 }
686 #endif /* XP_WIN */
687
688 /******************************************************************************
689  * UNIX-only methods
690  *****************************************************************************/
691 #ifdef XP_UNIX
692 static void Redraw( Widget w, XtPointer closure, XEvent *event )
693 {
694     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
695     const NPWindow *window = p_plugin->getWindow();
696     GC gc;
697     XGCValues gcv;
698
699     Window  drawable   = (Window) window->window;
700     Display *p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
701
702     gcv.foreground = BlackPixel( p_display, 0 );
703     gc = XCreateGC( p_display, drawable, GCForeground, &gcv );
704
705     XFillRectangle( p_display, drawable, gc,
706                     0, 0, window->width, window->height );
707
708     gcv.foreground = WhitePixel( p_display, 0 );
709     XChangeGC( p_display, gc, GCForeground, &gcv );
710
711     XDrawString( p_display, drawable, gc,
712                  window->width / 2 - 40, window->height / 2,
713                  WINDOW_TEXT, strlen(WINDOW_TEXT) );
714
715     XFreeGC( p_display, gc );
716 }
717
718 static void Resize ( Widget w, XtPointer closure, XEvent *event )
719 {
720     VlcPlugin* p_plugin = reinterpret_cast<VlcPlugin*>(closure);
721     const NPWindow *window = p_plugin->getWindow();
722     Window  drawable   = (Window) window->window;
723     Display *p_display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
724
725     int i_ret;
726     Window root_return, parent_return, * children_return;
727     Window base_window;
728     unsigned int i_nchildren;
729
730 #ifdef X11_RESIZE_DEBUG
731     XWindowAttributes attr;
732
733     if( event && event->type == ConfigureNotify )
734     {
735         fprintf( stderr, "vlcshell::Resize() ConfigureNotify %d x %d, "
736                  "send_event ? %s\n", event->xconfigure.width,
737                  event->xconfigure.height,
738                  event->xconfigure.send_event ? "TRUE" : "FALSE" );
739     }
740 #endif /* X11_RESIZE_DEBUG */
741
742     if( ! p_plugin->setSize(window->width, window->height) )
743     {
744         /* size already set */
745         return;
746     }
747
748
749     i_ret = XResizeWindow( p_display, drawable, window->width, window->height );
750
751 #ifdef X11_RESIZE_DEBUG
752     fprintf( stderr,
753              "vlcshell::Resize() XResizeWindow(owner) returned %d\n", i_ret );
754
755     XGetWindowAttributes ( p_display, drawable, &attr );
756
757     /* X is asynchronous, so the current size reported here is not
758        necessarily the requested size as the Resize request may not
759        yet have been handled by the plugin host */
760     fprintf( stderr, "vlcshell::Resize() current (owner) size %d x %d\n",
761              attr.width, attr.height );
762 #endif /* X11_RESIZE_DEBUG */
763
764     XQueryTree( p_display, drawable,
765                 &root_return, &parent_return, &children_return,
766                 &i_nchildren );
767
768     if( i_nchildren > 0 )
769     {
770         /* XXX: Make assumptions related to the window parenting structure in
771            vlc/modules/video_output/x11/xcommon.c */
772         base_window = children_return[i_nchildren - 1];
773
774 #ifdef X11_RESIZE_DEBUG
775         fprintf( stderr, "vlcshell::Resize() got %d children\n", i_nchildren );
776         fprintf( stderr, "vlcshell::Resize() got base_window %p\n",
777                  base_window );
778 #endif /* X11_RESIZE_DEBUG */
779
780         i_ret = XResizeWindow( p_display, base_window,
781                 window->width, window->height );
782
783 #ifdef X11_RESIZE_DEBUG
784         fprintf( stderr,
785                  "vlcshell::Resize() XResizeWindow(base) returned %d\n",
786                  i_ret );
787
788         XGetWindowAttributes( p_display, base_window, &attr );
789
790         fprintf( stderr, "vlcshell::Resize() new size %d x %d\n",
791                  attr.width, attr.height );
792 #endif /* X11_RESIZE_DEBUG */
793     }
794 }
795
796 #endif /* XP_UNIX */
797