]>
Commit | Line | Data |
---|---|---|
0fd734af JS |
1 | wxMicroWindows port |
2 | =================== | |
3 | ||
25ad2ac2 | 4 | Julian Smart 2001-12-08 |
0fd734af | 5 | |
bd52bee1 JS |
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. | |
0fd734af JS |
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 | |
bd52bee1 JS |
14 | converter. There are no common dialogs (we will use generic ones), |
15 | and only one WIN32 app may be run at a time. | |
0fd734af | 16 | |
bd52bee1 JS |
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. | |
0fd734af JS |
23 | |
24 | Installation | |
25 | ============ | |
26 | ||
bd52bee1 | 27 | MicroWindows: |
0fd734af | 28 | |
25ad2ac2 | 29 | - unarchive MicroWindows 0.89pre8 |
46d0e4b2 JS |
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 | ||
2a7449f4 JS |
40 | Note: these are already applied by the patch below. |
41 | ||
46d0e4b2 | 42 | - apply microwindows.patches (from wxWindows: |
bd52bee1 | 43 | docs/microwin/microwindows.patches) to fix PeekMessage |
25ad2ac2 | 44 | and other issues. If the patch doesn't apply automatically, |
2a7449f4 JS |
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 | |
46d0e4b2 | 52 | |
bd52bee1 JS |
53 | - compile by typing 'make' from within the MicroWindows src directory |
54 | ||
55 | wxMicroWindows: | |
56 | ||
25ad2ac2 | 57 | - Download wxMSW 2.3.2 or greater, or get it from CVS |
c67d6888 JS |
58 | |
59 | - Copy include/wx/msw/setup_microwin.h to include/wx/setup.h if | |
60 | include/wx/setup.h doesn't exist | |
46d0e4b2 | 61 | |
d2913c40 JS |
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 | |
46d0e4b2 | 72 | |
25ad2ac2 JS |
73 | - type 'make -f makefile.mic all' from src/msw. To clean, use |
74 | cleanwx and NOT clean since that will clean MicroWindows itself | |
46d0e4b2 | 75 | |
d2913c40 JS |
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' | |
0fd734af | 78 | |
0fd734af JS |
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 | ||
46d0e4b2 JS |
86 | The minimal sample is almost fully-functional, apart from minor |
87 | menu presentation issues (no borders, for example). | |
bd52bee1 JS |
88 | |
89 | Implementation Notes | |
90 | ==================== | |
0fd734af | 91 | |
bd52bee1 JS |
92 | wxMicroWindows is essentially the wxMSW port + wxUniversal |
93 | widgets. Lots of things in include/wx/univ/setup.h are switched | |
94 | off to allow the port to compile. There are also #ifdefs | |
95 | switching off further functionality, such as most wxBitmap | |
96 | functions, pending proper implementation. | |
0fd734af | 97 | |
bd52bee1 JS |
98 | There are some WIN32 API functions not implemented by MicroWindows |
99 | that are instead stubbed out in include/wx/msw/microwin.c, | |
100 | and 'implemented' in src/msw/microwin.c. Some of these functions | |
101 | are important, some less so. They will need to be implemented | |
102 | in due course. But implementing missing functionality in this way | |
103 | is preferably to proliferating many #ifdefs in the | |
104 | wxMSW/wxMicroWindows port itself. | |
105 | ||
106 | Things missing from MicroWindows that need to be worked around | |
107 | ============================================================== | |
108 | ||
e640f823 JS |
109 | wxImage/inline XPM/::CreateBitmap support |
110 | ----------------------------------------- | |
111 | ||
112 | This is the main obstacle to getting a good range | |
113 | of widgets working, since wxUniversal uses inline XPMs | |
114 | to implement most of the widgets. | |
115 | ||
116 | See src/engine/devimage.c for routines for loading JPEGs, | |
117 | XPMs etc. Unfortunately the XPM routines are also #ifdefed | |
118 | for FILE_IO, even though for inline XPMs we don't need file I/O. | |
119 | (Embedded systems tend not to have file I/O, anyway.) | |
120 | ||
121 | Now, wxWindows has its own XPM decoder, src/common/xpmdecod.cpp, | |
122 | so in theory we don't need to use MicroWindows' code there. | |
123 | wxImage can load an inline XPM, _but_ we need to convert to | |
124 | a wxBitmap since this is what the widgets need. | |
125 | ||
126 | There is no ::CreateBitmap or BITMAPINFO. (BMPs can be converted | |
127 | to C using convbmp, then need to use Gr... functions.) | |
128 | ||
129 | So how can we convert from wxImage to wxBitmap in MicroWindows? | |
130 | ||
131 | Well, a simple-minded way would be to use CreateCompatibleBitmap | |
132 | which returns an HBITMAP, select it into an HDC, and draw | |
133 | the pixels from the wxImage to the HDC one by one with SetPixel. | |
134 | ||
135 | ||
136 | Other missing features | |
137 | ---------------------- | |
138 | ||
bd52bee1 JS |
139 | No ::GetKeyState (see include/wx/msw/private.h). Should probably use |
140 | GdOpenKeyboard/GdCloseKeyboard/GdReadKeyboard. Could perhaps emulate | |
141 | GetKeyState this way. | |
0fd734af | 142 | |
0fd734af JS |
143 | No ::DestroyIcon, ::DestroyCursor - use ::DestroyObject instead? |
144 | Also no LoadCursor, LoadImage. So how do we make cursors? No ::SetCursor. | |
145 | ||
146 | wxDC: no ::GetTextColor, ::GetBkColor, ::IntersectClipRect, | |
147 | ::GetClipBox | |
148 | ||
bd52bee1 JS |
149 | No ::SetMenu, so no menus or menubars (now implemented by |
150 | wxUniversal). | |
0fd734af JS |
151 | |
152 | No ::GetObject so we can't get LOGFONT from an HFONT | |
bd52bee1 JS |
153 | in wxSystemSettings (worked around by passing HFONT to |
154 | the wxFont constructor). | |
0fd734af | 155 | |
2a7449f4 JS |
156 | |
157 | Applying patches by hand | |
158 | ======================== | |
159 | ||
160 | The full altered functions are given below in case you have | |
161 | to apply them by hand. | |
162 | ||
163 | src/mwin/winevent.c | |
164 | ------------------- | |
165 | ||
166 | A second test has been added to this line: | |
167 | ||
168 | if(hittest == HTCLIENT || hwnd == GetCapture()) { | |
169 | ||
170 | in MwTranslateMouseMessage below. This corrects a mouse message | |
171 | bug. | |
172 | ||
173 | /* | |
174 | * Translate and deliver hardware mouse message to proper window. | |
175 | */ | |
176 | void | |
177 | MwTranslateMouseMessage(HWND hwnd,UINT msg,int hittest) | |
178 | { | |
179 | POINT pt; | |
180 | DWORD tick; | |
181 | static UINT lastmsg = 0; | |
182 | static HWND lasthwnd; | |
183 | static DWORD lasttick; | |
184 | static int lastx, lasty; | |
185 | ||
186 | /* determine double click eligibility*/ | |
187 | if(msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN) { | |
188 | tick = GetTickCount(); | |
189 | if((hwnd->pClass->style & CS_DBLCLKS) && | |
190 | msg == lastmsg && hwnd == lasthwnd && | |
191 | tick - lasttick < DBLCLICKSPEED && | |
192 | abs(cursorx-lastx) < mwSYSMETRICS_CXDOUBLECLK && | |
193 | abs(cursory-lasty) < mwSYSMETRICS_CYDOUBLECLK) | |
194 | msg += (WM_LBUTTONDBLCLK - WM_LBUTTONDOWN); | |
195 | lastmsg = msg; | |
196 | lasthwnd = hwnd; | |
197 | lasttick = tick; | |
198 | lastx = cursorx; | |
199 | lasty = cursory; | |
200 | } | |
201 | ||
202 | /* | |
203 | * We always send nc mouse message | |
204 | * unlike Windows, for HTCLIENT default processing | |
205 | */ | |
206 | PostMessage(hwnd, msg + (WM_NCMOUSEMOVE-WM_MOUSEMOVE), hittest, | |
207 | MAKELONG(cursorx, cursory)); | |
208 | ||
209 | /* then possibly send user mouse message*/ | |
210 | if(hittest == HTCLIENT || hwnd == GetCapture()) { | |
211 | pt.x = cursorx; | |
212 | pt.y = cursory; | |
213 | ScreenToClient(hwnd, &pt); | |
214 | PostMessage(hwnd, msg, 0, MAKELONG(pt.x, pt.y)); | |
215 | } | |
216 | } | |
217 | ||
218 | winuser.c | |
219 | --------- | |
220 | ||
221 | Part of PeekMessage has been factored out into PeekMessageHelper, | |
222 | and used in PeekMessage and GetMessage. The three relevant functions | |
223 | are: | |
224 | ||
225 | /* | |
226 | * A helper function for sharing code between PeekMessage and GetMessage | |
227 | */ | |
228 | ||
229 | BOOL WINAPI | |
230 | PeekMessageHelper(LPMSG lpMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax, | |
231 | UINT wRemoveMsg, BOOL returnIfEmptyQueue) | |
232 | { | |
233 | HWND wp; | |
234 | PMSG pNxtMsg; | |
235 | ||
236 | /* check if no messages in queue*/ | |
237 | if(mwMsgHead.head == NULL) { | |
238 | /* Added by JACS so it doesn't reach MwSelect */ | |
239 | if (returnIfEmptyQueue) | |
240 | return FALSE; | |
241 | ||
242 | #if PAINTONCE | |
243 | /* check all windows for pending paint messages*/ | |
244 | for(wp=listwp; wp; wp=wp->next) { | |
245 | if(!(wp->style & WS_CHILD)) { | |
246 | if(chkPaintMsg(wp, lpMsg)) | |
247 | return TRUE; | |
248 | } | |
249 | } | |
250 | for(wp=listwp; wp; wp=wp->next) { | |
251 | if(wp->style & WS_CHILD) { | |
252 | if(chkPaintMsg(wp, lpMsg)) | |
253 | return TRUE; | |
254 | } | |
255 | } | |
256 | #endif | |
257 | MwSelect(); | |
258 | } | |
259 | ||
260 | if(mwMsgHead.head == NULL) | |
261 | return FALSE; | |
262 | ||
263 | pNxtMsg = (PMSG)mwMsgHead.head; | |
264 | if(wRemoveMsg & PM_REMOVE) | |
265 | GdListRemove(&mwMsgHead, &pNxtMsg->link); | |
266 | *lpMsg = *pNxtMsg; | |
267 | if(wRemoveMsg & PM_REMOVE) | |
268 | GdItemFree(pNxtMsg); | |
269 | return TRUE; | |
270 | } | |
271 | ||
272 | BOOL WINAPI | |
273 | PeekMessage(LPMSG lpMsg, HWND hwnd, UINT uMsgFilterMin, UINT uMsgFilterMax, | |
274 | UINT wRemoveMsg) | |
275 | { | |
276 | /* Never wait in MwSelect: pass TRUE */ | |
277 | return PeekMessageHelper(lpMsg, hwnd, uMsgFilterMin, uMsgFilterMax, wRemoveMsg, TRUE); | |
278 | } | |
279 | ||
280 | BOOL WINAPI | |
281 | GetMessage(LPMSG lpMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax) | |
282 | { | |
283 | /* | |
284 | * currently MwSelect() must poll for VT switch reasons, | |
285 | * so this code will work | |
286 | */ | |
287 | /* Always wait in MwSelect if there are messages: pass FALSE */ | |
288 | while(!PeekMessageHelper(lpMsg, hwnd, wMsgFilterMin, wMsgFilterMax,PM_REMOVE, FALSE)) | |
289 | continue; | |
290 | return lpMsg->message != WM_QUIT; | |
291 | } |