ed3153faa84ef4dd9a0461c911653b88605443b1
[vlc.git] / modules / gui / skins / x11 / x11_window.cpp
1 /*****************************************************************************
2  * x11_window.cpp: X11 implementation of the Window class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: x11_window.cpp,v 1.11 2003/06/07 00:36:28 asmax Exp $
6  *
7  * Authors: Cyril Deguet     <asmax@videolan.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., 59 Temple Place - Suite 330, Boston, MA  02111,
22  * USA.
23  *****************************************************************************/
24
25 #ifdef X11_SKINS
26
27 //--- GENERAL ---------------------------------------------------------------
28 //#include <math.h>
29
30 //--- VLC -------------------------------------------------------------------
31 #include <vlc/intf.h>
32
33 //--- X11 -------------------------------------------------------------------
34 #include <X11/Xlib.h>
35 #include <X11/extensions/shape.h>
36
37 //--- SKIN ------------------------------------------------------------------
38 #include "../os_api.h"
39 #include "../src/anchor.h"
40 #include "../controls/generic.h"
41 #include "../src/window.h"
42 #include "../os_window.h"
43 #include "../src/event.h"
44 #include "../os_event.h"
45 #include "../src/graphics.h"
46 #include "../os_graphics.h"
47 #include "../src/skin_common.h"
48 #include "../src/theme.h"
49 #include "../os_theme.h"
50
51
52 //---------------------------------------------------------------------------
53 // Skinable Window
54 //---------------------------------------------------------------------------
55 X11Window::X11Window( intf_thread_t *p_intf, Window wnd, int x, int y,
56     bool visible, int transition, int normalalpha, int movealpha,
57     bool dragdrop, string name )
58     : SkinWindow( p_intf, x, y, visible, transition, normalalpha, movealpha,
59               dragdrop )
60 {
61     // Set handles
62     Wnd           = wnd;
63
64     display = p_intf->p_sys->display;
65     int screen = DefaultScreen( display );
66
67     Gc = DefaultGC( display, screen );
68
69     Name        = name;
70
71     LButtonDown = false;
72     RButtonDown = false;
73
74     // Removing fading effect
75     Transition  = 0;
76 /*
77     // Set position parameters
78     CursorPos    = new POINT;
79     WindowPos    = new POINT;
80
81     // Create Tool Tip Window
82     ToolTipWindow = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL,
83         WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
84         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
85         hWnd, 0, GetModuleHandle( NULL ), 0);
86
87     // Create Tool Tip infos
88     ToolTipInfo.cbSize = sizeof(TOOLINFO);
89     ToolTipInfo.uFlags = TTF_SUBCLASS|TTF_IDISHWND;
90     ToolTipInfo.hwnd = hWnd;
91     ToolTipInfo.hinst = GetModuleHandle( NULL );
92     ToolTipInfo.uId = (unsigned int)hWnd;
93     ToolTipInfo.lpszText = NULL;
94     ToolTipInfo.rect.left = ToolTipInfo.rect.top = 0;
95         ToolTipInfo.rect.right = ToolTipInfo.rect.bottom = 0;
96
97     SendMessage( ToolTipWindow, TTM_ADDTOOL, 0,
98                     (LPARAM)(LPTOOLINFO) &ToolTipInfo );
99 */
100
101     if( DragDrop )
102     {
103         // register the listview as a drop target
104         DropObject = new X11DropObject( p_intf );
105     //    gdk_window_register_dnd( gwnd );
106     }
107
108     // Create Tool Tip window
109     ToolTipWindow = XCreateSimpleWindow( display, wnd, 0, 0, 1, 1, 0, 0, 0 );
110
111     // Double-click handling
112     ClickedX = 0;
113     ClickedY = 0;
114     ClickedTime = 0;
115     // TODO: can be retrieved somewhere ?
116     DblClickDelay = 400;
117    
118 }
119 //---------------------------------------------------------------------------
120 X11Window::~X11Window()
121 {
122 /*    delete CursorPos;
123     delete WindowPos;
124
125     if( hWnd != NULL )
126     {
127         DestroyWindow( hWnd );
128     }*/
129     XDestroyWindow( display, ToolTipWindow );
130     /*
131     if( DragDrop )
132     {
133         // Remove the listview from the list of drop targets
134         RevokeDragDrop( hWnd );
135         DropTarget->Release();
136         // Uninitialize the OLE library
137         OleUninitialize();
138     }*/
139  /*   if( gWnd )
140     {
141         gdk_window_destroy( gWnd );
142     }*/
143 }
144 //---------------------------------------------------------------------------
145 void X11Window::OSShow( bool show )
146 {
147     if( show )
148     {
149         XLOCK;
150         XMapWindow( display, Wnd );
151         XMoveWindow( display, Wnd, Left, Top );
152         XUNLOCK;
153     }
154     else
155     {
156         XLOCK;
157         XUnmapWindow( display, Wnd );
158         XUNLOCK;
159     }
160 }
161 //---------------------------------------------------------------------------
162 bool X11Window::ProcessOSEvent( Event *evt )
163 {
164     unsigned int msg = evt->GetMessage();
165     unsigned int p1  = evt->GetParam1();
166     int          p2  = evt->GetParam2();
167     int          time;
168     int          posX, posY;
169
170     switch( msg )
171     {
172         case Expose:
173             RefreshFromImage( 0, 0, Width, Height );
174             return true;
175
176         case MotionNotify:
177             if( LButtonDown )
178                 MouseMove( (int)( (XMotionEvent *)p2 )->x,
179                            (int)( (XMotionEvent *)p2 )->y, 1 );
180             else if( RButtonDown )
181                 MouseMove( (int)( (XMotionEvent *)p2 )->x,
182                            (int)( (XMotionEvent *)p2 )->y, 2 );
183             else
184                 MouseMove( (int)( (XMotionEvent *)p2 )->x,
185                            (int)( (XMotionEvent *)p2 )->y, 0 );
186             return true;
187
188
189         case ButtonPress:
190             // Raise all the windows
191             for( list<SkinWindow *>::const_iterator win = 
192                     p_intf->p_sys->p_theme->WindowList.begin();
193                     win != p_intf->p_sys->p_theme->WindowList.end(); win++ )
194             {
195                 XLOCK;
196                 XRaiseWindow( display, ( (X11Window *)(*win) )->GetHandle() );
197                 XUNLOCK;
198             }
199
200             switch( ( (XButtonEvent *)p2 )->button )
201             {
202                 case 1:
203                     // Left button
204                     time = OSAPI_GetTime();
205                     OSAPI_GetMousePos( posX, posY );
206                     if( time - ClickedTime < DblClickDelay && 
207                         posX == ClickedX && posY == ClickedY )
208                     {
209                         // Double-click
210                         ClickedTime = 0; 
211                         MouseDblClick( (int)( (XButtonEvent *)p2 )->x,
212                                        (int)( (XButtonEvent *)p2 )->y, 1 );
213                     }
214                     else
215                     {
216                         ClickedTime = time;
217                         ClickedX = posX;
218                         ClickedY = posY;
219                         LButtonDown = true;
220                         MouseDown( (int)( (XButtonEvent *)p2 )->x,
221                                    (int)( (XButtonEvent *)p2 )->y, 1 );
222                     }
223                     break;
224
225                 case 3:
226                     // Right button
227                     RButtonDown = true;
228                     MouseDown( (int)( (XButtonEvent *)p2 )->x,
229                                (int)( (XButtonEvent *)p2 )->y, 2 );
230                     break;
231
232                 default:
233                     break;
234             }
235             return true;
236
237         case ButtonRelease:
238             switch( ( (XButtonEvent *)p2 )->button )
239             {
240                 case 1:
241                     // Left button
242                     LButtonDown = false;
243                     MouseUp( (int)( (XButtonEvent *)p2 )->x,
244                              (int)( (XButtonEvent *)p2 )->y, 1 );
245                     break;
246
247                 case 3:
248                     // Right button
249                     RButtonDown = false;
250                     MouseUp( (int)( (XButtonEvent *)p2 )->x,
251                              (int)( (XButtonEvent *)p2 )->y, 2 );
252                     break; 
253                     
254                 case 4:
255                     // Scroll up
256                     MouseScroll( (int)( (XButtonEvent *)p2 )->x,
257                                  (int)( (XButtonEvent *)p2 )->y,
258                                  MOUSE_SCROLL_UP);
259                     break;
260                     
261                 case 5:
262                     // Scroll down
263                     MouseScroll( (int)( (XButtonEvent *)p2 )->x,
264                                  (int)( (XButtonEvent *)p2 )->y,
265                                  MOUSE_SCROLL_DOWN);
266                     break;
267
268                 default:
269                     break;
270             }
271             return true;
272
273         case LeaveNotify:
274             OSAPI_PostMessage( this, WINDOW_LEAVE, 0, 0 );
275             return true;
276
277 /*        case GDK_DROP_START:
278             DropObject->HandleDropStart( ( (GdkEventDND *)p2 )->context );
279             return true;
280 */
281         default:
282             return false;
283     }
284 }
285 //---------------------------------------------------------------------------
286 void X11Window::SetTransparency( int Value )
287 {
288 /*    if( Value > -1 )
289         Alpha = Value;
290     SetLayeredWindowAttributes( hWnd, 0, Alpha, LWA_ALPHA | LWA_COLORKEY );
291     UpdateWindow( hWnd );*/
292 }
293 //---------------------------------------------------------------------------
294 void X11Window::RefreshFromImage( int x, int y, int w, int h )
295 {
296     Drawable drawable = (( X11Graphics* )Image )->GetImage();
297     
298     XLOCK;
299     XCopyArea( display, drawable, Wnd, Gc, x, y, w, h, x, y );
300  
301     XImage *image = XGetImage( display, drawable, 0, 0, Width, Height, 
302                                AllPlanes, ZPixmap );
303  
304     // Mask for transparency
305     Region region = XCreateRegion();
306     for( int line = 0; line < Height; line++ )
307     {
308         int start = 0, end = 0;
309         while( start < Width )
310         {
311             while( start < Width && XGetPixel( image, start, line ) == 0 )
312             {
313                 start++;
314             } 
315             end = start;
316             while( end < Width && XGetPixel( image, end, line ) != 0)
317             {
318                 end++;
319             }
320             XRectangle rect;
321             rect.x = start;
322             rect.y = line;
323             rect.width = end - start + 1;
324             rect.height = 1;
325             Region newRegion = XCreateRegion();
326             XUnionRectWithRegion( &rect, region, newRegion );
327             XDestroyRegion( region );
328             region = newRegion;
329             start = end + 1;
330         }
331     }
332     XShapeCombineRegion( display, Wnd, ShapeBounding, 0, 0, region, ShapeSet );
333     XDestroyRegion( region );
334
335     XSync( display, 0);
336     XUNLOCK;
337 }
338 //---------------------------------------------------------------------------
339 void X11Window::WindowManualMove()
340 {
341     // Get mouse cursor position
342     int x, y;
343     OSAPI_GetMousePos( x, y );
344
345     // Move window and chek for magnetism
346     p_intf->p_sys->p_theme->MoveSkinMagnet( this,
347         WindowX + x - CursorX, WindowY + y - CursorY );
348
349 }
350 //---------------------------------------------------------------------------
351 void X11Window::WindowManualMoveInit()
352 {
353     OSAPI_GetMousePos( CursorX, CursorY );
354     WindowX = Left;
355     WindowY = Top;
356 }
357 //---------------------------------------------------------------------------
358 void X11Window::Move( int left, int top )
359 {
360     Left = left;
361     Top  = top;
362     XMoveWindow( display, Wnd, left, top );
363 }
364 //---------------------------------------------------------------------------
365 void X11Window::Size( int width, int height )
366 {
367     Width  = width;
368     Height = height;
369     XResizeWindow( display, Wnd, width, height );
370 }
371 //---------------------------------------------------------------------------
372 void X11Window::ChangeToolTipText( string text )
373 {
374     if( text == "none" )
375     {
376         if( ToolTipText != "none" )
377         {
378             ToolTipText = "none";
379 //            ToolTipInfo.lpszText = NULL;
380  //           SendMessage( ToolTipWindow, TTM_ACTIVATE, 0 , 0 );
381         }
382     }
383     else
384     {
385         if( text != ToolTipText )
386         {
387             ToolTipText = text;
388   //          ToolTipInfo.lpszText = (char *)ToolTipText.c_str();
389   /*          SendMessage( ToolTipWindow, TTM_ACTIVATE, 1 , 0 );
390             SendMessage( ToolTipWindow, TTM_UPDATETIPTEXT, 0,
391                              (LPARAM)(LPTOOLINFO)&ToolTipInfo );*/
392         }
393     }
394 }
395 //---------------------------------------------------------------------------
396
397 #endif