Mercurial > sdl-ios-xcode
annotate src/cdrom/mint/SDL_syscdrom.c @ 1287:15a89a0c52bf
Date: Tue, 15 Feb 2005 21:28:48 +0900 (JST)
From: "Michael Leonhard"
Subject: [SDL] resize bug on Win32 and patch
This is my first post to this mailing list. In this email I will detail a
bug in the behavior of resizable SDL windows on Win32. Then I will
explain the solution and provide a patch.
Symptoms:
Under Windows, an SDL display created with the SDL_RESIZABLE flag exhibits
quirky behavior when being maximized. The window is resized to the proper
size, but it is shifted upwards about half the height of the title bar.
Similarly, a window whose origin is above the top of the screen will
spontaneously move its upper-left origin upon being resized. After two
such resize-induced moves, the title bar will be entirely off the top edge
of the screen. Subsequently, when the mouse is clicked and released on
the window border, the window will shrink its height spontaneously. This
height shrinkage occurs even if the user did not resize the border.
To observe this curious situation, please invoke:
SDL-1.2.8/test/testwm.exe -resize
Cause:
A pair of integers, SDL_windowX and SDL_windowY, are defined in
video/wincommon/SDL_sysevents.c. They are used by the DirectX video
driver and the DIB video driver:
video/windx5/SDL_dx5video.c
video/windib/SDL_dibvideo.c
As I understand the source code, the primary use of these variables is to
create a rectangle that represents the surface area in CLIENT SPACE.
Client space refers to a coordinate system that originates at the upper
left corner of a Win32 Window's drawable area. This is just inside the
window border and title bar. This client space rectangle, called bounds,
is subsequently converted to screen space with a call to
AdjustWindowRectEx. The problem is found in SDL's handling of the
WM_WINDOWPOSCHANGED message. According to MSDN,
"The WM_WINDOWPOSCHANGED message is sent to a window whose
size, position, or place in the Z order has changed as a
result of a call to the SetWindowPos function or another
window-management function."
I have confirmed that this message is indeed being sent to the SDL window
when the mouse is clicked on the window border, even if the window border
is not dragged.
In video/wincommon/SDL_sysevents.c, on line 464, in response to the
WM_WINDOWPOSCHANGED message, the (potentially) new client rectangle is
obtained. This rectangle is translated into screen coordinates and THEN
assigned to the SDL_windowX and Y variables. Thus screen coordinates are
being assigned to client coordinate variables. Once this is understood,
the solution is apparent: assign SDL_windowX and Y before translating the
rectangle to screen coordinates. This is accomplished by the following
patch.
-Mike_L
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 29 Jan 2006 08:50:06 +0000 |
parents | b8d311d90021 |
children | 604d73db6802 |
rev | line source |
---|---|
724 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
727
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
724 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 | |
23 /* | |
24 Atari MetaDOS CD-ROM functions | |
25 | |
26 Patrice Mandin | |
27 */ | |
28 | |
29 #include <errno.h> | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 | |
34 #include <cdromio.h> | |
35 #include <metados.h> | |
36 | |
37 #include "SDL_error.h" | |
38 #include "SDL_cdrom.h" | |
39 #include "SDL_syscdrom.h" | |
40 | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
41 /* Some ioctl() errno values which occur when the tray is empty */ |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
42 #ifndef ENOMEDIUM |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
43 #define ENOMEDIUM ENOENT |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
44 #endif |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
45 #define ERRNO_TRAYEMPTY(errno) \ |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
46 ((errno == EIO) || (errno == ENOENT) || \ |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
47 (errno == EINVAL) || (errno == ENOMEDIUM)) |
724 | 48 |
49 /* The maximum number of CD-ROM drives we'll detect */ | |
50 #define MAX_DRIVES 32 | |
51 | |
52 typedef struct { | |
53 unsigned char device[3]; /* Physical device letter + ':' + '\0' */ | |
54 metaopen_t metaopen; /* Infos on opened drive */ | |
55 } metados_drive_t; | |
56 | |
57 static metados_drive_t metados_drives[MAX_DRIVES]; | |
58 | |
59 /* The system-dependent CD control functions */ | |
60 static const char *SDL_SYS_CDName(int drive); | |
61 static int SDL_SYS_CDOpen(int drive); | |
62 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
63 static int SDL_SYS_CDioctl(int id, int command, void *arg); | |
64 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
65 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
66 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
67 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
68 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
69 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
70 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
71 | |
72 int SDL_SYS_CDInit(void) | |
73 { | |
74 metainit_t metainit={0,0,0,0}; | |
75 metaopen_t metaopen; | |
76 int i, handle; | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
77 struct cdrom_subchnl info; |
724 | 78 |
79 Metainit(&metainit); | |
80 if (metainit.version == NULL) { | |
81 #ifdef DEBUG_CDROM | |
82 fprintf(stderr, "MetaDOS not installed\n"); | |
83 #endif | |
84 return -1; | |
85 } | |
86 | |
87 if (metainit.drives_map == 0) { | |
88 #ifdef DEBUG_CDROM | |
89 fprintf(stderr, "No MetaDOS devices present\n"); | |
90 #endif | |
91 return -1; | |
92 } | |
93 | |
94 SDL_numcds = 0; | |
95 | |
96 for (i='A'; i<='Z'; i++) { | |
97 metados_drives[SDL_numcds].device[0] = 0; | |
98 metados_drives[SDL_numcds].device[1] = ':'; | |
99 metados_drives[SDL_numcds].device[2] = 0; | |
100 | |
101 if (metainit.drives_map & (1<<(i-'A'))) { | |
102 handle = Metaopen(i, &metaopen); | |
103 if (handle == 0) { | |
104 | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
105 info.cdsc_format = CDROM_MSF; |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
106 if ( (Metaioctl(i, METADOS_IOCTL_MAGIC, CDROMSUBCHNL, &info) == 0) || ERRNO_TRAYEMPTY(errno) ) { |
724 | 107 metados_drives[SDL_numcds].device[0] = i; |
108 ++SDL_numcds; | |
109 } | |
110 | |
111 Metaclose(i); | |
112 } | |
113 } | |
114 } | |
115 | |
116 /* Fill in our driver capabilities */ | |
117 SDL_CDcaps.Name = SDL_SYS_CDName; | |
118 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
119 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
120 | |
121 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
122 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
123 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
124 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
125 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
126 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
127 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
128 | |
129 return 0; | |
130 } | |
131 | |
132 void SDL_SYS_CDQuit(void) | |
133 { | |
134 SDL_numcds = 0; | |
135 } | |
136 | |
137 static const char *SDL_SYS_CDName(int drive) | |
138 { | |
139 return(metados_drives[drive].device); | |
140 } | |
141 | |
142 static int SDL_SYS_CDOpen(int drive) | |
143 { | |
144 int handle; | |
145 | |
146 handle = Metaopen(metados_drives[drive].device[0], &(metados_drives[drive].metaopen)); | |
147 if (handle == 0) { | |
148 return drive; | |
149 } | |
150 | |
151 return -1; | |
152 } | |
153 | |
154 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
155 { | |
156 Metaclose(metados_drives[cdrom->id].device[0]); | |
157 } | |
158 | |
159 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
160 { | |
161 int retval; | |
162 | |
163 retval = Metaioctl(metados_drives[id].device[0], METADOS_IOCTL_MAGIC, command, arg); | |
164 if ( retval < 0 ) { | |
165 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
166 } | |
167 return(retval); | |
168 } | |
169 | |
170 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
171 { | |
172 int i,okay; | |
173 struct cdrom_tochdr toc; | |
174 struct cdrom_tocentry entry; | |
175 | |
176 /* Use standard ioctl() */ | |
177 if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)<0) { | |
178 return -1; | |
179 } | |
180 | |
181 cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1; | |
182 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
183 cdrom->numtracks = SDL_MAX_TRACKS; | |
184 } | |
185 | |
186 /* Read all the track TOC entries */ | |
187 okay=1; | |
188 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
189 if ( i == cdrom->numtracks ) { | |
190 cdrom->track[i].id = CDROM_LEADOUT; | |
191 } else { | |
192 cdrom->track[i].id = toc.cdth_trk0+i; | |
193 } | |
194 entry.cdte_track = cdrom->track[i].id; | |
195 entry.cdte_format = CDROM_MSF; | |
196 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, &entry) < 0 ) { | |
197 okay=0; | |
198 break; | |
199 } else { | |
200 if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) { | |
201 cdrom->track[i].type = SDL_DATA_TRACK; | |
202 } else { | |
203 cdrom->track[i].type = SDL_AUDIO_TRACK; | |
204 } | |
205 cdrom->track[i].offset = MSF_TO_FRAMES( | |
206 entry.cdte_addr.msf.minute, | |
207 entry.cdte_addr.msf.second, | |
208 entry.cdte_addr.msf.frame); | |
209 cdrom->track[i].length = 0; | |
210 if ( i > 0 ) { | |
211 cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset; | |
212 } | |
213 } | |
214 } | |
215 | |
216 return(okay ? 0 : -1); | |
217 } | |
218 | |
219 /* Get CD-ROM status */ | |
220 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
221 { | |
222 CDstatus status; | |
223 struct cdrom_tochdr toc; | |
224 struct cdrom_subchnl info; | |
225 | |
226 info.cdsc_format = CDROM_MSF; | |
227 if ( SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) { | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
228 if ( ERRNO_TRAYEMPTY(errno) ) { |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
229 status = CD_TRAYEMPTY; |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
230 } else { |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
231 status = CD_ERROR; |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
232 } |
724 | 233 } else { |
234 switch (info.cdsc_audiostatus) { | |
235 case CDROM_AUDIO_INVALID: | |
236 case CDROM_AUDIO_NO_STATUS: | |
237 /* Try to determine if there's a CD available */ | |
238 if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) { | |
239 status = CD_STOPPED; | |
240 } else { | |
241 status = CD_TRAYEMPTY; | |
242 } | |
243 break; | |
244 case CDROM_AUDIO_COMPLETED: | |
245 status = CD_STOPPED; | |
246 break; | |
247 case CDROM_AUDIO_PLAY: | |
248 status = CD_PLAYING; | |
249 break; | |
250 case CDROM_AUDIO_PAUSED: | |
251 /* Workaround buggy CD-ROM drive */ | |
252 if ( info.cdsc_trk == CDROM_LEADOUT ) { | |
253 status = CD_STOPPED; | |
254 } else { | |
255 status = CD_PAUSED; | |
256 } | |
257 break; | |
258 default: | |
259 status = CD_ERROR; | |
260 break; | |
261 } | |
262 } | |
263 if ( position ) { | |
264 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
265 *position = MSF_TO_FRAMES( | |
266 info.cdsc_absaddr.msf.minute, | |
267 info.cdsc_absaddr.msf.second, | |
268 info.cdsc_absaddr.msf.frame); | |
269 } else { | |
270 *position = 0; | |
271 } | |
272 } | |
273 return(status); | |
274 } | |
275 | |
276 /* Start play */ | |
277 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
278 { | |
279 struct cdrom_msf playtime; | |
280 | |
281 FRAMES_TO_MSF(start, | |
282 &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0); | |
283 FRAMES_TO_MSF(start+length, | |
284 &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1); | |
285 #ifdef DEBUG_CDROM | |
286 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
287 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0, | |
288 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1); | |
289 #endif | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
290 |
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
291 return SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime); |
724 | 292 } |
293 | |
294 /* Pause play */ | |
295 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
296 { | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
297 return SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0); |
724 | 298 } |
299 | |
300 /* Resume play */ | |
301 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
302 { | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
303 return SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0); |
724 | 304 } |
305 | |
306 /* Stop play */ | |
307 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
308 { | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
309 return SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0); |
724 | 310 } |
311 | |
312 /* Eject the CD-ROM */ | |
313 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
314 { | |
727
cb1208fcd946
Update MiNT CD-ROM driver
Patrice Mandin <patmandin@gmail.com>
parents:
724
diff
changeset
|
315 return SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0); |
724 | 316 } |