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