Dear WINE developers,
I develop an MS windows app and just got it working under WINE/Linux. It's call LTspice/SwitcherCADIII. It's a free schematic capture/SPICE simulator obtainable from www.linear.com/software.
I've noticed a few things about WINE that might help you improve it. WINE can confuse SendMessage() with PostMessage(). LTspice uses SendMessage to handshake between threads sometimes. Wine usually obeys the difference, but treated some SendMessage calls like a PostMessage. My workaround was to poll volatile global variables.
I needed to add some redraws to clear up some differences between WINE and Windows dialog box updates. This was for a tab control that make different controls on the pane visible or not depending on tab selection. Also LTspice draws directly to the screen and carefully counts the number of times it XOR'ed something with the screen. That behaved a bit different between WINE and Windows. Again, I found workarounds for most of it. I'm not sure, but maybe it's just a difference between obeying the SetROP2() setting for CDC::SetPixel() calls.
The version of LTspice I put up on the web today, 2.01c, works quite well under WINE/Linux. The main problem with it is that the RoboHelp isn't working. Any advice there?
A few other WINE issues:
1. The icons drawn on Property sheet tabs have a black background in WINE. In Windows it's the background color. You can see the problem on the Tools=>Control Panel tab icons.
2. The resize grip on the lower right hand corner of resizeable dialogs is drawn like a scrollbar. The "proper" windows method to draw these resize grips is to use a scroll bar created like this:
CScrollBar m_Grip;
char OldResizableGrip[] = "OldResizableGrip"; LRESULT CALLBACK GripWindowProc(HWND hwnd, UINT msg, WPARAM wParam,LPARAM lParam) { if(WM_NCHITTEST == msg) return(HTBOTTOMRIGHT); // the mouse cursor that goes with a grip on the bottom right of a window HANDLE oldWndProc = GetProp(hwnd, OldResizableGrip); if(WM_DESTROY == msg) // unsubclass { RemoveProp(hwnd, OldResizableGrip); SetWindowLong(hwnd, GWL_WNDPROC, (LONG) oldWndProc); } return(CallWindowProc((WNDPROC) oldWndProc, hwnd, msg, wParam,lParam)); }
BOOL CSelectWaveformsDlg::OnInitDialog() { CDialog::OnInitDialog(); SetAllListBoxItems(); CRect rect(0, 0, GetSystemMetrics(SM_CXVSCROLL),GetSystemMetrics(SM_CYHSCROLL)); m_Grip.Create(WS_CHILD | WS_CLIPSIBLINGS | SBS_SIZEGRIP | WS_VISIBLE,rect, this, AFX_IDW_SIZE_BOX); CWnd *resizeWnd = GetDlgItem(AFX_IDW_SIZE_BOX); if(resizeWnd) { CRect rect, rect2; resizeWnd->GetWindowRect(&rect); GetClientRect(rect2); rect2.left = rect2.right - rect.Width(); rect2.top = rect2.bottom - rect.Height(); resizeWnd->MoveWindow(&rect2, FALSE); ::SetProp(m_Grip, OldResizableGrip, (HANDLE) ::GetWindowLong(m_Grip, GWL_WNDPROC)); ::SetWindowLong(m_Grip, GWL_WNDPROC, (LONG) GripWindowProc); } return(TRUE); }
3. Function key F6 is not trapped.
4. The cursor colors are off. For example, the voltage probe cursor should have a red body. In WINE it's black. The sleeve of the pointing hand is blue, in WINE it's black.
5. Font's aren't always correct. There's two types for schematics, "Arial" and "New Courier". The Arial can become italic depending on the size required.
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
--Mike Engelhardt pmte@concentric.net
"Mike Engelhardt" pmte@concentric.net writes:
I've noticed a few things about WINE that might help you improve it. WINE can confuse SendMessage() with PostMessage(). LTspice uses SendMessage to handshake between threads sometimes. Wine usually obeys the difference, but treated some SendMessage calls like a PostMessage. My workaround was to poll volatile global variables.
I'd be interested to hear more details; SendMessage is definitely supposed to behave properly.
Alexandre,
I've noticed a few things about WINE that might help you improve it. WINE can confuse SendMessage() with PostMessage(). LTspice uses SendMessage to handshake between threads sometimes. Wine usually obeys the difference, but treated some SendMessage calls like a PostMessage. My workaround was to poll volatile global variables.
I'd be interested to hear more details; SendMessage is definitely supposed to behave properly.
Here's the situation: The app has two threads. One is the whole MDI/user interface/CAD and text editor. The worker thread does a simulation of the circuit you draw in the CAD editor. The messages are all registered messages for a historical reason in a footnote(1).
The first message back from the worker thread says it's got some partial data to plot and sends a message to the view window that launched the thread. The view knows the name of the file containing the data and launches a doc/view to read it. That doc/view throws up a dialog asking which data to plot. The schematic doc/view and plotting doc/view handshake here by calling each other's functions and setting each other's data members. After the data is read, the original view to get the message from the working thread returns the number of data points that were found in the file. All this time the worker thread, having done a SendMessage() and not a PostMessage(), is frozen waiting for the return value of the number of points so it can decide where to try again or continue. The scheme that I'm using has been extensively debugged and used under 95,98,Me,NT,2K, and XP. But under wine, the worker thread doesn't freeze when it calls SendMessage() but keeps executing. It's imperative that it does because on subsequent calls from the worker to the UI thread, it sends little compressed packets of data. The UI must process these before the worker thread continues.
//Here's the code that worked under Windows:
int nPnts = SendMessage(TheChartWindow, WM_MARCH_INIT, 0, 0); if(nPnts != run->pointCount) // try again if it failed SendMessage(TheChartWindow, WM_MARCH_INIT, 0, 0);
// And here's the code hacked to work under Wine: volatile BOOL LinuxProcessed = FALSE; volatile int NumberPoints = 0;
unsigned MarchInit() { NumberPoints = 0; LinuxProcessed = FALSE; SendMessage(TheChartWindow, WM_MARCH_INIT, 0, 0); // the function that receives this will // assign the return value to NumberPoints // and assign a value to LinuxProcessed while(!LinuxProcessed) // Will Wine every simply ever lose the message? Do I need to time-out? Sleep(100); return(NumberPoints); }
int nPnts = MarchInit(); if(nPnts != run->pointCount) MarchInit();
I did find one other problem in Wine that may or may not be related to messaging, that being with the FindReplace common dialog. When you press "Find Next" which is IDOK, under Wine nothings happened in my app. My app uses one FindReplace dialog for all document types and relates the command to the active document. The workaround was to add an OnOK() handler:
// Wine is a global BOOL the TRUE if running under Wine void CFindDlg::OnOK() // for WINE { // for WINE if(Wine) // for WINE
{ // for WINE WineFindReplaceHack = TRUE; // for WINE LPARAM lParam = (unsigned ) this + offsetof(CFindReplaceDialog, m_fr); // for WINE ::SendMessage(theApp.m_pMainWnd->m_hWnd, WM_FINDREPLACE, 0, lParam); // for WINE WineFindReplaceHack = FALSE; // for WINE } // for WINE else // for WINE Default(); // for WINE } // for WINE
LRESULT CMainFrame::OnFindString(WPARAM wParam, LPARAM lParam) { CFindDlg *dlg = (CFindDlg *) CFindReplaceDialog::GetNotifier(lParam); . . . if(WineFindReplaceHack || dlg->FindNext()) { // search active document for dlg->m_findWindowText and highlight. } . . . return(0); }
Let me know if you have any other questions. I'd like to be as helpful as I can in this and immensely appreciate the help that, e.g., Uwe has been. I officially feel guilty that I'm not subscribed to the e-mail list, but I get too many e-mails and phone calls as it is.
--Mike
(1) Normally the graphical schematic drives the worker thread. but a text netlist can also be used. I used to use a CEditView for this netlist and under Win95, the original message scheme didn't work until I used registered messages. I no longer use a CEditView but an more general purpose syntax colonizing editor with unlimited undo/redo, so i don't know if the messages still have to be registered.
"Mike Engelhardt" pmte@concentric.net writes:
All this time the worker thread, having done a SendMessage() and not a PostMessage(), is frozen waiting for the return value of the number of points so it can decide where to try again or continue. The scheme that I'm using has been extensively debugged and used under 95,98,Me,NT,2K, and XP. But under wine, the worker thread doesn't freeze when it calls SendMessage() but keeps executing.
This definitely doesn't sound right. If you have a chance, could you please do a --debugmsg +server,+message trace showing the problem? That would help a lot in tracking this down.
On Thursday 27 February 2003 04:29 pm, Mike Engelhardt wrote:
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
In my app startup, I look for the environmental variable "_". Under Windows, it will likely not even exist. Under Wine, it will tell you something like "/usr/local/bin/wine". I save this to a global variable called _WINE. That way, no matter where I am in my app I can check the value of _WINE to decide which branch to execute. I haven't had to use this yet, and hope not to, but built it in already just in case.
HTH
Thank you very much. Uwe suggested a method along these lines:
HMODULE hModule = GetModuleHandle("kernel32"); BOOL Wine = hModule && GetProcAddress(hModule, "wine_get_unix_file_name");
It'd be a good thing to put in a FAQ. I couldn't find it anyway.
--Mike
----- Original Message ----- From: "Paul McNett" p@ulmcnett.com To: "Mike Engelhardt" pmte@concentric.net; wine-devel@winehq.com Sent: Friday, February 28, 2003 10:38 AM Subject: Re: Report after porting a windows app to WINE
On Thursday 27 February 2003 04:29 pm, Mike Engelhardt wrote:
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
In my app startup, I look for the environmental variable "_". Under Windows, it will likely not even exist. Under Wine, it will tell you something like "/usr/local/bin/wine". I save this to a global variable called _WINE. That way, no matter where I am in my app I can check the value of _WINE to decide which branch to execute. I haven't had to use this yet, and hope not to, but built it in already just in case.
HTH
-- Paul McNett - p@ulmcnett.com Hollister, California, USA
Paul McNett wrote:
On Thursday 27 February 2003 04:29 pm, Mike Engelhardt wrote:
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
the real best way is to fix the behavior in Wine, not try to get around it. so, any good bugreport is also more than welcomed in order to have it fixed
A+
Eric ,
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
the real best way is to fix the behavior in Wine, not try to get around it. so, any good bugreport is also more than welcomed in order to have it fixed
I thought I had reported bugs in my first breath. Doesn't change my requirement to have my app run under 95, 98, Me, NT, 2K, XP and any reasonably recent release of Wine. Each OS as had it's own share of workarounds required as is common for a really large app. Anyway, I don't find it unreasonable to have to work around specific bugs in specific OS's.
--Mike
I thought I had reported bugs in my first breath. Doesn't change my requirement to have my app run under 95, 98, Me, NT, 2K, XP and any reasonably recent release of Wine. Each OS as had it's own share of workarounds required as is common for a really large app. Anyway, I don't find it unreasonable to have to work around specific bugs in specific OS's.
Well yes, but Wine isn't meant to be a specific OS as such, it's meant to emulate any version of Windows required. I mean you can work around problems in Wine, but ideally we'd be altering our bugs to match those in the real Windows, that makes peoples lives easier in future (users and developers). Bear in mind that while you _have_ to work around bugs in Windows because of the slow release cycle and closed source nature, in Wine it's possible to fix the bugs directly, so you shouldn't treat them the same way.
BTW to be most useful a bugreport would ideally be in bugzilla with the relevant parts of the traces, although debugging such things yourself is usually the best approach.
thanks -mike
- Function key F6 is not trapped.
Can you explain this one a bit further? You mean Wine doesn't forward it to the app?
- The cursor colors are off. For example, the voltage probe cursor should have a red body. In WINE it's black. The sleeve of the pointing hand is blue, in WINE it's black.
Ah, I think that's not a bug in wine per se, as up until yesterday no stable release of X could actually do coloured cursors. The XCursor extension that comes in with XFree 4.3 adds support for colour, animated, alpha blended cursors, as opposed to the old system that was 1 bit only.
The solution here is to add support for XCursor uploads to Wine. File a bug against it I guess, write it yourself, or hire a Wine developer to do it for you.
I would like to know if there is a way to determine if my app is running under WINE under runtime. That way I can work around more of these problems without imparing its performance under MS Windows. If you know the answer, please e-mail me directly.
As has already been pointed out, it'd be much better for you to actually fix bugs in Wine rather than work around them in your own app when possible - that way, everybody wins :) In particular, if in the future the bug is fixed, your workarounds will either break or become redundant.
thanks -mike
Mike,
- Function key F6 is not trapped.
Can you explain this one a bit further? You mean Wine doesn't forward it to the app?
The function looks like this:
void CecsView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) { . . . if (113 == nChar) // F2, add component OnPlaceComp(); else if(114 == nChar) // F3, add wire OnDrawWires(); else if(115 == nChar) // F4, place net OnPlaceNet(); else if((116 == nChar) || (46 == nChar)) // F5(or delete key), delete stuff OnDeleteStuff(); else if(117 == nChar) // F6, duplicate stuff OnDuplicate(); else if(118 == nChar) // F7, move stuff OnMoveStuff(); else if(119 == nChar) // F8, drag stuff OnDragStuff(); else if(120 == nChar) // F9, undo HistoryUndoStep(); . . . CScrollView::OnKeyUp(nChar, nRepCnt, nFlags); }
Pressing F2, F3, F4, F5, F7, F8 and F9 all go to the right place. Nothing happens when F6 is pressed. Why is that?
On Fri, 2003-02-28 at 21:19, Mike Engelhardt wrote:
Mike,
- Function key F6 is not trapped.
Can you explain this one a bit further? You mean Wine doesn't forward it to the app?
The function looks like this:
void CecsView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
Bear in mind quite a few people here don't know C++ :) I get the idea though.
Pressing F2, F3, F4, F5, F7, F8 and F9 all go to the right place. Nothing happens when F6 is pressed. Why is that?
No idea, but that kind of thing should be fairly easy to debug, it's probably just a missed out or incorrect table entry. Try reading the part about debug channels in the users guide and looking at keyboard logs.
----- Original Message ----- From: "Mike Hearn" mike@theoretic.com To: "Mike Engelhardt" pmte@concentric.net Cc: wine-devel@winehq.com Sent: Friday, February 28, 2003 1:52 PM Subject: Re: Report after porting a windows app to WINE
On Fri, 2003-02-28 at 21:19, Mike Engelhardt wrote:
Mike,
- Function key F6 is not trapped.
Can you explain this one a bit further? You mean Wine doesn't forward it to the app?
The function looks like this:
void CecsView::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) {
Bear in mind quite a few people here don't know C++ :) I get the idea though.
Pressing F2, F3, F4, F5, F7, F8 and F9 all go to the right place. Nothing happens when F6 is pressed. Why is that?
No idea, but that kind of thing should be fairly easy to debug, it's probably just a missed out or incorrect table entry. Try reading the part about debug channels in the users guide and looking at keyboard logs.
I put a messagebox in OnKeyUp() to tell me what nChar it's getting. It enters OnKeyUp() for every function key except F6. If I hold down the control key, then it also get's F6 and it get's it with the right key code, 117. Could Gnome be trapping that key for something?
Other than that, I put up a new version today, 2.01c, that works pretty well under WINE except for this F6 issue and that the RoboHelp system does't work yet.
--Mike
I put a messagebox in OnKeyUp() to tell me what nChar it's getting. It enters OnKeyUp() for every function key except F6. If I hold down the control key, then it also get's F6 and it get's it with the right key code, 117. Could Gnome be trapping that key for something?
Yes, that's possible. Like I said, use the channels Luke!
wine --debugmsg +keyboard foo.exe
then watch what is printed when you hit a key. If nothing appears when you press F6, probably the window manager is eating it before it gets to wine (try running it in a different setup to test that theory).
Other than that, I put up a new version today, 2.01c, that works pretty well under WINE except for this F6 issue and that the RoboHelp system does't work yet.
--Mike
Mike,
I put a messagebox in OnKeyUp() to tell me what nChar it's getting. It enters OnKeyUp() for every function key except F6. If I hold down the control key, then it also get's F6 and it get's it with the
right
key code, 117. Could Gnome be trapping that key for something?
Yes, that's possible. Like I said, use the channels Luke!
wine --debugmsg +keyboard foo.exe
then watch what is printed when you hit a key. If nothing appears when you press F6, probably the window manager is eating it before it gets to wine (try running it in a different setup to test that theory).
Thank-you . No debugmsg when I press F6. Any idea where I change that in the window manager?
--Mike