[10/10] x11drv / user: Fix 32bpp (BGRA) cursors
[wine/hacks.git] / server / cursoricon.c
blobd69f3904d7afc58366c7d09d66cc7c38721e79c0
1 /*
2 * Server-side cursors / icons
4 * Copyright 2007 Henri Verbeet
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "ntstatus.h"
24 #define WIN32_NO_STATUS
25 #include "winternl.h"
26 #include "object.h"
27 #include "request.h"
28 #include "user.h"
30 typedef struct {
31 unsigned short xhot;
32 unsigned short yhot;
33 unsigned short width;
34 unsigned short height;
35 unsigned short and_width_bytes;
36 unsigned short xor_width_bytes;
37 unsigned char planes;
38 unsigned char bpp;
39 /* bits contains both the AND and XOR bitmap data, in that order */
40 unsigned char *bits;
41 } cursor_frame_t;
43 typedef struct {
44 struct process *process;
45 unsigned int num_frames;
46 unsigned int delay;
47 cursor_frame_t *frames;
48 } cursor_t;
50 void destroy_cursor( cursor_t *cursor )
52 unsigned int i;
54 for (i = 0; i < cursor->num_frames; ++i)
56 free( cursor->frames[i].bits );
59 free( cursor->frames );
60 free( cursor );
63 /* destroy all cursors belonging to a given process */
64 void destroy_process_cursors( struct process *process )
66 user_handle_t handle = 0;
67 cursor_t *cursor;
69 while ((cursor = next_user_handle( &handle, USER_CURSOR )))
71 if (cursor->process != process) continue;
73 destroy_cursor( cursor );
74 free_user_handle( handle );
78 /* Create a cursor */
79 DECL_HANDLER(create_cursor)
81 cursor_t *cursor = mem_alloc( sizeof(cursor_t) );
82 cursor->process = current->process;
83 cursor->num_frames = req->num_frames;
84 cursor->delay = req->delay;
85 cursor->frames = mem_alloc( req->num_frames * sizeof(cursor_frame_t) );
86 memset( cursor->frames, 0, req->num_frames * sizeof(cursor_frame_t) );
88 reply->handle = alloc_user_handle( cursor, USER_CURSOR );
91 /* Destroy a cursor */
92 DECL_HANDLER(destroy_cursor)
94 cursor_t *cursor = free_user_handle( req->handle );
96 if (cursor) destroy_cursor( cursor );
99 /* Get cursor info */
100 DECL_HANDLER(get_cursor_info)
102 cursor_t *cursor = get_user_object( req->handle, USER_CURSOR );
104 if (!cursor) return;
106 reply->num_frames = cursor->num_frames;
107 reply->delay = cursor->delay;
110 /* Get frame info & bitmap bits */
111 DECL_HANDLER(get_cursor_frame)
113 unsigned int data_size;
114 unsigned int frame_idx = req->frame_idx;
115 cursor_t *cursor = get_user_object( req->handle, USER_CURSOR );
116 cursor_frame_t *frame;
118 if (!cursor || cursor->num_frames < frame_idx)
120 reply->height = 0;
121 return;
124 frame = &cursor->frames[frame_idx];
126 reply->xhot = frame->xhot;
127 reply->yhot = frame->yhot;
128 reply->width = frame->width;
129 reply->height = frame->height;
130 reply->and_width_bytes = frame->and_width_bytes;
131 reply->xor_width_bytes = frame->xor_width_bytes;
132 reply->planes = frame->planes;
133 reply->bpp = frame->bpp;
135 data_size = (frame->and_width_bytes + frame->xor_width_bytes) * frame->height;
136 if (data_size > get_reply_max_size())
138 set_error( STATUS_BUFFER_OVERFLOW );
139 return;
142 set_reply_data( frame->bits, data_size );
145 /* Set frame info & bitmap bits */
146 DECL_HANDLER(set_cursor_frame)
148 size_t data_size = get_req_data_size();
149 unsigned int frame_idx = req->frame_idx;
150 cursor_t *cursor = get_user_object( req->handle, USER_CURSOR );
151 cursor_frame_t *frame;
153 if (!cursor || cursor->num_frames < frame_idx || !data_size) return;
155 frame = &cursor->frames[frame_idx];
157 frame->xhot = req->xhot;
158 frame->yhot = req->yhot;
159 frame->width = req->width;
160 frame->height = req->height;
161 frame->and_width_bytes = req->and_width_bytes;
162 frame->xor_width_bytes = req->xor_width_bytes;
163 frame->planes = req->planes;
164 frame->bpp = req->bpp;
166 free( frame->bits );
167 frame->bits = memdup( get_req_data(), data_size );