]>
Commit | Line | Data |
---|---|---|
1 | wxMicroWindows port | |
2 | =================== | |
3 | ||
4 | Julian Smart 2001-12-08 | |
5 | ||
6 | This is a port of wxWindows to MicroWindows, under Linux. | |
7 | Widgets are supplied by the wxUniversal project, while the | |
8 | underlying port uses the Windows ports with small modifications | |
9 | for the MicroWindows API. | |
10 | ||
11 | There are many things missing from MicroWindows that will | |
12 | make the port quite limited for the time being. I haven't | |
13 | worked out how to create bitmaps, though there is a BMP to C | |
14 | converter. There are no common dialogs (we will use generic ones), | |
15 | and only one WIN32 app may be run at a time. | |
16 | ||
17 | Note that you can gain confidence in the WIN32/wxUniversal | |
18 | combination by compiling wxUniversal under Windows using VC++, | |
19 | using src/wxvc_universal.dsp. You can compile the minimal | |
20 | and widgets samples in wxUniversal mode using the | |
21 | UnivDebug and UnivRelease targets. Most of the code is shared | |
22 | between this combination, and the wxMicroWindows port. | |
23 | ||
24 | Installation | |
25 | ============ | |
26 | ||
27 | MicroWindows: | |
28 | ||
29 | - unarchive MicroWindows 0.89pre8 | |
30 | ||
31 | - change 'config' to use X11 and any other options you feel fit. | |
32 | Suggestions for changes to the defaults: | |
33 | ||
34 | ERASEMOVE=N (otherwise moving windows will look messy) | |
35 | X11=Y | |
36 | OPTIMIZE=N | |
37 | DEBUG=Y | |
38 | VERBOSE=Y | |
39 | ||
40 | Note: these are already applied by the patch below. | |
41 | ||
42 | - apply microwindows.patches (from wxWindows: | |
43 | docs/microwin/microwindows.patches) to fix PeekMessage | |
44 | and other issues. If the patch doesn't apply automatically, | |
45 | you may need to apply it by hand, and the relevant changed | |
46 | functions are given at the end of this file for convenience. | |
47 | ||
48 | Example patch command: | |
49 | ||
50 | % cd microwindows-0.89pre8.orig | |
51 | % patch -p0 < ~/wx2/docs/microwin/microwindows.patches | |
52 | ||
53 | - compile by typing 'make' from within the MicroWindows src directory | |
54 | ||
55 | wxMicroWindows: | |
56 | ||
57 | - Download wxMSW 2.3.2 or greater, or get it from CVS | |
58 | ||
59 | - Copy include/wx/msw/setup_microwin.h to include/wx/setup.h if | |
60 | include/wx/setup.h doesn't exist | |
61 | ||
62 | - EITHER: | |
63 | ||
64 | o set the MICROWINDOWS environment variable, e.g.: | |
65 | ||
66 | % export MICROWINDOWS=/home/julians/local/microwindows/microwindows-0.89pre8/src | |
67 | ||
68 | OR: | |
69 | ||
70 | o change the TOP variable at the top of src/msw/makefile.mic | |
71 | to reflect where MicroWindows is installed | |
72 | ||
73 | - type 'make -f makefile.mic all' from src/msw. To clean, use | |
74 | cleanwx and NOT clean since that will clean MicroWindows itself | |
75 | ||
76 | - to make the sample, cd into samples/minimal, edit the TOP variable | |
77 | (or set MICROWINDOWS) as before, and type 'make -f makefile.mic all' | |
78 | ||
79 | Running 'minimal' runs the virtual MicroWindows desktop | |
80 | and the minimal sample, since in a MicroWindows WIN32 application | |
81 | they are one and the same binary. | |
82 | ||
83 | Status | |
84 | ====== | |
85 | ||
86 | The minimal sample is almost fully-functional, apart from some | |
87 | presentation issues (no menu borders and status bar in the wrong | |
88 | place. | |
89 | ||
90 | The widgets sample is crashing in DeleteObject (see notes below). | |
91 | ||
92 | ||
93 | Implementation Notes | |
94 | ==================== | |
95 | ||
96 | wxMicroWindows is essentially the wxMSW port + wxUniversal | |
97 | widgets. Lots of things in include/wx/univ/setup.h are switched | |
98 | off to allow the port to compile. There are also #ifdefs | |
99 | switching off further functionality, such as most wxBitmap | |
100 | functions, pending proper implementation. | |
101 | ||
102 | There are some WIN32 API functions not implemented by MicroWindows | |
103 | that are instead stubbed out in include/wx/msw/microwin.c, | |
104 | and 'implemented' in src/msw/microwin.c. Some of these functions | |
105 | are important, some less so. They will need to be implemented | |
106 | in due course. But implementing missing functionality in this way | |
107 | is preferably to proliferating many #ifdefs in the | |
108 | wxMSW/wxMicroWindows port itself. | |
109 | ||
110 | ||
111 | Errors/warnings | |
112 | =============== | |
113 | ||
114 | In file ../../src/msw/window.cpp at line 1294: 'UpdateWindow' failed with error 0x00000000 (Success). | |
115 | ||
116 | - caused because there are no paint messages pending. Presumed | |
117 | harmless. | |
118 | ||
119 | In file ../../src/msw/dc.cpp at line 1838: 'BitBlt' failed with error 0x00000000 (Success). | |
120 | ||
121 | - caused because the window isn't mapped, and MwPrepareDC in wingdi.c | |
122 | fails (hwnd->unmapcount is non-zero). Presumed harmless. | |
123 | ||
124 | Recursive paint problem, e.g. when clicking the 'Press Me!' | |
125 | button in the widgets sample a few times, until the text control | |
126 | is full. | |
127 | ||
128 | - possibly the scrollbar is causing the text control to be | |
129 | updated, which somehow effects the scrollbar, which causes | |
130 | a window update, etc. | |
131 | ||
132 | Sluggish updates. | |
133 | ||
134 | - probably because many image to bitmap conversions are being | |
135 | done on update, and bitmaps should probably be cached. | |
136 | ||
137 | ||
138 | Things missing from MicroWindows that need to be worked around | |
139 | ============================================================== | |
140 | ||
141 | wxImage/inline XPM/::CreateBitmap support | |
142 | ----------------------------------------- | |
143 | ||
144 | This is the main obstacle to getting a good range | |
145 | of widgets working, since wxUniversal uses inline XPMs | |
146 | to implement most of the widgets. | |
147 | ||
148 | See src/engine/devimage.c for routines for loading JPEGs, | |
149 | XPMs etc. Unfortunately the XPM routines are also #ifdefed | |
150 | for FILE_IO, even though for inline XPMs we don't need file I/O. | |
151 | (Embedded systems tend not to have file I/O, anyway.) | |
152 | ||
153 | Now, wxWindows has its own XPM decoder, src/common/xpmdecod.cpp, | |
154 | so in theory we don't need to use MicroWindows' code there. | |
155 | wxImage can load an inline XPM, _but_ we need to convert to | |
156 | a wxBitmap since this is what the widgets need. | |
157 | ||
158 | There is no ::CreateBitmap or BITMAPINFO. (BMPs can be converted | |
159 | to C using convbmp, then need to use Gr... functions.) | |
160 | ||
161 | So how can we convert from wxImage to wxBitmap in MicroWindows? | |
162 | ||
163 | Well, a simple-minded way would be to use CreateCompatibleBitmap | |
164 | which returns an HBITMAP, select it into an HDC, and draw | |
165 | the pixels from the wxImage to the HDC one by one with SetPixel. | |
166 | This is now implemented, but there are problems with masks. | |
167 | (a) masks have to be created at screen depth because BitBlt/GrDraw | |
168 | can't cope with differing depths, and (b) masked blitting | |
169 | is still not working (try enabling mask creation in | |
170 | wxBitmap::CreateFromImage by setting USE_MASKS to 1). | |
171 | ||
172 | ||
173 | Other missing features | |
174 | ---------------------- | |
175 | ||
176 | No ::GetKeyState (see include/wx/msw/private.h). Should probably use | |
177 | GdOpenKeyboard/GdCloseKeyboard/GdReadKeyboard. Could perhaps emulate | |
178 | GetKeyState this way. | |
179 | ||
180 | No ::DestroyIcon, ::DestroyCursor - use ::DestroyObject instead? | |
181 | Also no LoadCursor, LoadImage. So how do we make cursors? No ::SetCursor. | |
182 | ||
183 | wxDC: no ::GetTextColor, ::GetBkColor, ::IntersectClipRect, | |
184 | ::GetClipBox | |
185 | ||
186 | No ::SetMenu, so no menus or menubars (now implemented by | |
187 | wxUniversal). | |
188 | ||
189 | No ::GetObject so we can't get LOGFONT from an HFONT | |
190 | in wxSystemSettings (worked around by passing HFONT to | |
191 | the wxFont constructor). | |
192 | ||
193 | ||
194 | Applying patches by hand | |
195 | ======================== | |
196 | ||
197 | The full altered functions are given below in case you have | |
198 | to apply them by hand. | |
199 | ||
200 | src/mwin/winevent.c | |
201 | ------------------- | |
202 | ||
203 | A second test has been added to this line: | |
204 | ||
205 | if(hittest == HTCLIENT || hwnd == GetCapture()) { | |
206 | ||
207 | in MwTranslateMouseMessage below. This corrects a mouse message | |
208 | bug. | |
209 | ||
210 | /* | |
211 | * Translate and deliver hardware mouse message to proper window. | |
212 | */ | |
213 | void | |
214 | MwTranslateMouseMessage(HWND hwnd,UINT msg,int hittest) | |
215 | { | |
216 | POINT pt; | |
217 | DWORD tick; | |
218 | static UINT lastmsg = 0; | |
219 | static HWND lasthwnd; | |
220 | static DWORD lasttick; | |
221 | static int lastx, lasty; | |
222 | ||
223 | /* determine double click eligibility*/ | |
224 | if(msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN) { | |
225 | tick = GetTickCount(); | |
226 | if((hwnd->pClass->style & CS_DBLCLKS) && | |
227 | msg == lastmsg && hwnd == lasthwnd && | |
228 | tick - lasttick < DBLCLICKSPEED && | |
229 | abs(cursorx-lastx) < mwSYSMETRICS_CXDOUBLECLK && | |
230 | abs(cursory-lasty) < mwSYSMETRICS_CYDOUBLECLK) | |
231 | msg += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); | |
232 | lastmsg = msg; | |
233 | lasthwnd = hwnd; | |
234 | lasttick = tick; | |
235 | lastx = cursorx; | |
236 | lasty = cursory; | |
237 | } | |
238 | ||
239 | /* | |
240 | * We always send nc mouse message | |
241 | * unlike Windows, for HTCLIENT default processing | |
242 | */ | |
243 | PostMessage(hwnd, msg + (WM_NCMOUSEMOVE-WM_MOUSEMOVE), hittest, | |
244 | MAKELONG(cursorx, cursory)); | |
245 | ||
246 | /* then possibly send user mouse message*/ | |
247 | if(hittest == HTCLIENT || hwnd == GetCapture()) { | |
248 | pt.x = cursorx; | |
249 | pt.y = cursory; | |
250 | ScreenToClient(hwnd, &pt); | |
251 | PostMessage(hwnd, msg, 0, MAKELONG(pt.x, pt.y)); | |
252 | } | |
253 | } | |
254 | ||
255 | winuser.c | |
256 | --------- | |
257 | ||
258 | Part of PeekMessage has been factored out into PeekMessageHelper, | |
259 | and used in PeekMessage and GetMessage. The three relevant functions | |
260 | are: | |
261 | ||
262 | /* | |
263 | * A helper function for sharing code between PeekMessage and GetMessage | |
264 | */ | |
265 | ||
266 | BOOL WINAPI | |
267 | PeekMessageHelper(LPMSG lpMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax, | |
268 | UINT wRemoveMsg, BOOL returnIfEmptyQueue) | |
269 | { | |
270 | HWND wp; | |
271 | PMSG pNxtMsg; | |
272 | ||
273 | /* check if no messages in queue*/ | |
274 | if(mwMsgHead.head == NULL) { | |
275 | /* Added by JACS so it doesn't reach MwSelect */ | |
276 | if (returnIfEmptyQueue) | |
277 | return FALSE; | |
278 | ||
279 | #if PAINTONCE | |
280 | /* check all windows for pending paint messages*/ | |
281 | for(wp=listwp; wp; wp=wp->next) { | |
282 | if(!(wp->style & WS_CHILD)) { | |
283 | if(chkPaintMsg(wp, lpMsg)) | |
284 | return TRUE; | |
285 | } | |
286 | } | |
287 | for(wp=listwp; wp; wp=wp->next) { | |
288 | if(wp->style & WS_CHILD) { | |
289 | if(chkPaintMsg(wp, lpMsg)) | |
290 | return TRUE; | |
291 | } | |
292 | } | |
293 | #endif | |
294 | MwSelect(); | |
295 | } | |
296 | ||
297 | if(mwMsgHead.head == NULL) | |
298 | return FALSE; | |
299 | ||
300 | pNxtMsg = (PMSG)mwMsgHead.head; | |
301 | if(wRemoveMsg & PM_REMOVE) | |
302 | GdListRemove(&mwMsgHead, &pNxtMsg->link); | |
303 | *lpMsg = *pNxtMsg; | |
304 | if(wRemoveMsg & PM_REMOVE) | |
305 | GdItemFree(pNxtMsg); | |
306 | return TRUE; | |
307 | } | |
308 | ||
309 | BOOL WINAPI | |
310 | PeekMessage(LPMSG lpMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax, | |
311 | UINT wRemoveMsg) | |
312 | { | |
313 | /* Never wait in MwSelect: pass TRUE */ | |
314 | return PeekMessageHelper(lpMsg, hwnd, uMsgFilterMin, uMsgFilterMax, wRemoveMsg, TRUE); | |
315 | } | |
316 | ||
317 | BOOL WINAPI | |
318 | GetMessage(LPMSG lpMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax) | |
319 | { | |
320 | /* | |
321 | * currently MwSelect() must poll for VT switch reasons, | |
322 | * so this code will work | |
323 | */ | |
324 | /* Always wait in MwSelect if there are messages: pass FALSE */ | |
325 | while(!PeekMessageHelper(lpMsg, hwnd, wMsgFilterMin, wMsgFilterMax,PM_REMOVE, FALSE)) | |
326 | continue; | |
327 | return lpMsg->message != WM_QUIT; | |
328 | } |