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