Use mouse as capture retangle center instead of upper left corner.
[vlc.git] / modules / access / screen / x11.c
1 /*****************************************************************************
2  * x11.c: Screen capture module.
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/vlc.h>
33
34 #include <X11/Xlib.h>
35 #include <X11/Xutil.h>
36
37 #include "screen.h"
38
39 int screen_InitCapture( demux_t *p_demux )
40 {
41     demux_sys_t *p_sys = p_demux->p_sys;
42     Display *p_display;
43     XWindowAttributes win_info;
44     int i_chroma;
45
46     /* Open the display */
47     p_display = XOpenDisplay( NULL );
48     if( !p_display )
49     {
50         msg_Err( p_demux, "cannot open display" );
51         return VLC_EGENERIC;
52     }
53     p_sys->p_data = (void *)p_display;
54
55     /* Get the parameters of the root window */
56     if( !XGetWindowAttributes( p_display,
57                                DefaultRootWindow( p_display ),
58                                &win_info ) )
59     {
60         msg_Err( p_demux, "can't get root window attributes" );
61         XCloseDisplay( p_display );
62         return VLC_EGENERIC;
63     }
64
65     switch( win_info.depth )
66     {
67     case 8: /* FIXME: set the palette */
68         i_chroma = VLC_FOURCC('R','G','B','2'); break;
69     case 15:
70         i_chroma = VLC_FOURCC('R','V','1','5'); break;
71     case 16:
72         i_chroma = VLC_FOURCC('R','V','1','6'); break;
73     case 24:
74     case 32:
75         i_chroma = VLC_FOURCC('R','V','3','2');
76         win_info.depth = 32;
77         break;
78     default:
79         msg_Err( p_demux, "unknown screen depth %i", win_info.depth );
80         XCloseDisplay( p_display );
81         return VLC_EGENERIC;
82     }
83
84     es_format_Init( &p_sys->fmt, VIDEO_ES, i_chroma );
85     p_sys->fmt.video.i_width  = win_info.width;
86     p_sys->fmt.video.i_height = win_info.height;
87     p_sys->fmt.video.i_bits_per_pixel = win_info.depth;
88
89 #if 0
90     win_info.visual->red_mask;
91     win_info.visual->green_mask;
92     win_info.visual->blue_mask;
93     win_info.visual->bits_per_rgb;
94 #endif
95
96     return VLC_SUCCESS;
97 }
98
99 int screen_CloseCapture( demux_t *p_demux )
100 {
101     demux_sys_t *p_sys = p_demux->p_sys;
102     Display *p_display = (Display *)p_sys->p_data;
103
104     XCloseDisplay( p_display );
105     return VLC_SUCCESS;
106 }
107
108 block_t *screen_Capture( demux_t *p_demux )
109 {
110     demux_sys_t *p_sys = p_demux->p_sys;
111     Display *p_display = (Display *)p_sys->p_data;
112     block_t *p_block;
113     XImage *image;
114     int i_size;
115
116     if( p_sys->b_follow_mouse )
117     {
118         Window root = DefaultRootWindow( p_display ), child;
119         int root_x, root_y;
120         int win_x, win_y;
121         unsigned int mask;
122         if( XQueryPointer( p_display, root,
123             &root, &child, &root_x, &root_y, &win_x, &win_y,
124             &mask ) )
125         {
126             root_x -= p_sys->i_width/2;
127             if( root_x < 0 ) root_x = 0;
128             p_sys->i_left = __MIN( (unsigned int)root_x,
129                                    p_sys->i_screen_width - p_sys->i_width );
130             root_y -= p_sys->i_height/2;
131             if( root_y < 0 ) root_y = 0;
132             p_sys->i_top = __MIN( (unsigned int)root_y,
133                                   p_sys->i_screen_height - p_sys->i_height );
134         }
135         else
136             msg_Dbg( p_demux, "XQueryPointer() failed" );
137
138     }
139
140     image = XGetImage( p_display, DefaultRootWindow( p_display ),
141                        p_sys->i_left, p_sys->i_top, p_sys->fmt.video.i_width,
142                        p_sys->fmt.video.i_height, AllPlanes, ZPixmap );
143
144     if( !image )
145     {
146         msg_Warn( p_demux, "cannot get image" );
147         return 0;
148     }
149
150     i_size = image->bytes_per_line * image->height;
151
152     if( !( p_block = block_New( p_demux, i_size ) ) )
153     {
154         msg_Warn( p_demux, "cannot get block" );
155         XDestroyImage( image );
156         return 0;
157     }
158
159     vlc_memcpy( p_block->p_buffer, image->data, i_size );
160
161     XDestroyImage( image );
162
163     return p_block;
164 }
165