Release 960616
Sun Jun 16 16:51:31 1996 Alexandre Julliard <julliard@lrc.epfl.ch> * [memory/heap.c] Fixed bug in HeapRealloc (thanks to Bruce Milner). * [misc/wsprintf.c] Fixed argument size for %c format in wsprintf16(). * [objects/dc.c] Don't free hFirstBitmap for saved DCs. * [windows/event.c] Added timer handling in EVENT_WaitXEvent(). * [windows/message.c] In MSG_TranslateMouseMsg and MSG_TranslateKbdMsg, check if the event is for the current task; if not, wake the other task. * [windows/queue.c] [include/queue.h] Added 'self' handle in queue structure. * [windows/timer.c] Added TIMER_ExpireTimers() function to mark expired timers and wake up the corresponding tasks. Thu Jun 13 01:46:33 EDT 1996 William Magro <wmagro@tc.cornell.edu> * [windows/mapping.c] First point in list was mapped multiple times in DPtoLP and LPtoDP. Other points were not mapped. Wed Jun 12 18:08:45 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu> * [misc/shell.c] Some fixes for ExtractIcon function family. * [documentation/user_module] Chapter about windowing and messaging subsystems.
This commit is contained in:
parent
d90840e180
commit
8b91563079
14
ANNOUNCE
14
ANNOUNCE
|
@ -1,12 +1,12 @@
|
|||
This is release 960611 of Wine, the MS Windows emulator. This is still a
|
||||
This is release 960616 of Wine, the MS Windows emulator. This is still a
|
||||
developer's only release. There are many bugs and many unimplemented API
|
||||
features. Most applications still do not work correctly.
|
||||
|
||||
Patches should be submitted to "julliard@lrc.epfl.ch". Please don't
|
||||
forget to include a ChangeLog entry.
|
||||
|
||||
WHAT'S NEW with Wine-960611: (see ChangeLog for details)
|
||||
- (surprise) More Win32 code.
|
||||
WHAT'S NEW with Wine-960616: (see ChangeLog for details)
|
||||
- Inter-task messaging begins to work.
|
||||
- Lots of bug fixes.
|
||||
|
||||
See the README file in the distribution for installation instructions.
|
||||
|
@ -15,10 +15,10 @@ Because of lags created by using mirror, this message may reach you before
|
|||
the release is available at the ftp sites. The sources will be available
|
||||
from the following locations:
|
||||
|
||||
sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960611.tar.gz
|
||||
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960611.tar.gz
|
||||
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960611.tar.gz
|
||||
aris.com:/pub/linux/ALPHA/Wine/development/Wine-960611.tar.gz
|
||||
sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960616.tar.gz
|
||||
tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960616.tar.gz
|
||||
ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960616.tar.gz
|
||||
aris.com:/pub/linux/ALPHA/Wine/development/Wine-960616.tar.gz
|
||||
|
||||
It should also be available from any site that mirrors tsx-11 or sunsite.
|
||||
|
||||
|
|
40
ChangeLog
40
ChangeLog
|
@ -1,3 +1,43 @@
|
|||
----------------------------------------------------------------------
|
||||
Sun Jun 16 16:51:31 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
|
||||
|
||||
* [memory/heap.c]
|
||||
Fixed bug in HeapRealloc (thanks to Bruce Milner).
|
||||
|
||||
* [misc/wsprintf.c]
|
||||
Fixed argument size for %c format in wsprintf16().
|
||||
|
||||
* [objects/dc.c]
|
||||
Don't free hFirstBitmap for saved DCs.
|
||||
|
||||
* [windows/event.c]
|
||||
Added timer handling in EVENT_WaitXEvent().
|
||||
|
||||
* [windows/message.c]
|
||||
In MSG_TranslateMouseMsg and MSG_TranslateKbdMsg, check if the
|
||||
event is for the current task; if not, wake the other task.
|
||||
|
||||
* [windows/queue.c] [include/queue.h]
|
||||
Added 'self' handle in queue structure.
|
||||
|
||||
* [windows/timer.c]
|
||||
Added TIMER_ExpireTimers() function to mark expired timers and
|
||||
wake up the corresponding tasks.
|
||||
|
||||
Thu Jun 13 01:46:33 EDT 1996 William Magro <wmagro@tc.cornell.edu>
|
||||
|
||||
* [windows/mapping.c]
|
||||
First point in list was mapped multiple times in DPtoLP and
|
||||
LPtoDP. Other points were not mapped.
|
||||
|
||||
Wed Jun 12 18:08:45 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
|
||||
|
||||
* [misc/shell.c]
|
||||
Some fixes for ExtractIcon function family.
|
||||
|
||||
* [documentation/user_module]
|
||||
Chapter about windowing and messaging subsystems.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Tue Jun 11 15:20:43 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
|
||||
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
USER MODULE
|
||||
===========
|
||||
|
||||
USER implements windowing and messaging subsystems. It also
|
||||
contains code for common controls and for other miscellaneous
|
||||
stuff (rectangles, clipboard, WNet, etc). Wine USER code is
|
||||
located in windows/, controls/, and misc/ directories.
|
||||
|
||||
1. Windowing subsystem
|
||||
|
||||
Windows are arranged into parent/child hierarchy with one
|
||||
common ancestor for all windows (desktop window). Each window
|
||||
structure contains a pointer to the immediate ancestor (parent
|
||||
window if WS_CHILD style bit is set), a pointer to the sibling
|
||||
(returned by GetWindow(..., GW_NEXT)), a pointer to the owner
|
||||
window (set only for popup window if it was created with valid
|
||||
hwndParent parameter), and a pointer to the first child
|
||||
window (GetWindow(.., GW_CHILD)). All popup and non-child windows
|
||||
are therefore placed in the first level of this hierarchy and their
|
||||
ancestor link (wnd->parent) points to the desktop window.
|
||||
|
||||
Desktop window - root window
|
||||
| \ '-.
|
||||
| \ '-.
|
||||
popup -> wnd1 -> wnd2 - top level windows
|
||||
| \ '-. '-.
|
||||
| \ '-. '-.
|
||||
child1 child2 -> child3 child4 - child windows
|
||||
|
||||
Horizontal arrows denote sibling relationship, vertical lines
|
||||
- ancestor/child. To summarize, all windows with the same immediate
|
||||
ancestor are sibling windows, all windows which do not have desktop
|
||||
as their immediate ancestor are child windows. Popup windows behave
|
||||
as topmost top-level windows unless they are owned. In this case the
|
||||
only requirement is that they must precede their owners in the top-level
|
||||
sibling list (they are not topmost). Child windows are confined to the
|
||||
client area of their parent windows (client area is where window gets
|
||||
to do its own drawing, non-client area consists of caption, menu, borders,
|
||||
intrinsic scrollbars, and minimize/maximize/close buttons).
|
||||
|
||||
Another fairly important concept is "z-order". It is derived from
|
||||
the ancestor/child hierarchy and is used to determine "above/below"
|
||||
relationship. For instance, in the example above, z-order is
|
||||
child1->popup->child2->child3->wnd1->child4->wnd2->desktop. Current
|
||||
active window ("foreground window" in Win32) is moved to the front
|
||||
of z-order unless its top-level ancestor owns popup windows.
|
||||
|
||||
All these issues are dealt with (or supposed to be) in
|
||||
windows/winpos.c
|
||||
|
||||
Wine specifics: in default and managed mode each top-level window
|
||||
gets its own X counterpart with desktop window being basically a
|
||||
fake stub. In desktop mode, however, only desktop window has X
|
||||
window associated with it.
|
||||
|
||||
2. Messaging subsystem
|
||||
|
||||
Each Windows task/thread has its own message queue - this is where
|
||||
it gets messages from. Messages can be generated on the fly
|
||||
(WM_PAINT, WM_NCPAINT, WM_TIMER), they can be created by the system
|
||||
(hardware messages), they can be posted by other tasks/threads
|
||||
(PostMessage), or they can be sent by other tasks/threads (SendMessage).
|
||||
|
||||
Message priority:
|
||||
|
||||
First the system looks for sent messages, then for posted messages,
|
||||
then for hardware messages, then it checks if the queue has the
|
||||
"dirty window" bit set, and, finally, it checks for expired
|
||||
timers. See windows/message.c.
|
||||
|
||||
From all these different types of messages, only posted messages go
|
||||
directly into the private message queue. System messages (even in
|
||||
Win95) are first collected in the system message queue and then
|
||||
they either sit there until Get/PeekMessage gets to process them
|
||||
or, as in Win95, if system queue is getting clobbered, a special
|
||||
thread ("raw input thread") assigns them to the private
|
||||
queues. Sent messages are queued separately and the sender sleeps
|
||||
until it gets a reply. Special messages are generated on the fly
|
||||
depending on the window/queue state. If the window update region is
|
||||
not empty, the system sets the QS_PAINT bit in the owning queue and
|
||||
eventually this window receives a WM_PAINT message (WM_NCPAINT too
|
||||
if the update region intersects with the non-client area). A timer
|
||||
event is raised when one of the queue timers expire. Depending on
|
||||
the timer parameters DispatchMessage either calls the callback
|
||||
function or the window procedure. If there are no messages pending
|
||||
the task/thread sleeps until messages appear.
|
||||
|
||||
There are several tricky moments (open for discussion) -
|
||||
|
||||
a) System message order has to be honored and messages should be
|
||||
processed within correct task/thread context. Therefore when
|
||||
Get/PeekMessage encounters unassigned system message and this
|
||||
message appears not to be for the current task/thread it should
|
||||
either skip it (or get rid of it by moving it into the private
|
||||
message queue of the target task/thread - Win95, AFAIK) and
|
||||
look further or roll back and then yield until this message
|
||||
gets processed when system switches to the correct context
|
||||
(Win16). In the first case we lose correct message ordering, in
|
||||
the second case we have the infamous synchronous system message
|
||||
queue. Here is a post to one of the OS/2 newsgroup I found to
|
||||
be relevant:
|
||||
|
||||
" Here's the problem in a nutshell, and there is no good solution.
|
||||
Every possible solution creates a different problem.
|
||||
|
||||
With a windowing system, events can go to many different windows.
|
||||
Most are sent by applications or by the OS when things relating to
|
||||
that window happen (like repainting, timers, etc.)
|
||||
|
||||
Mouse input events go to the window you click on (unless some window
|
||||
captures the mouse).
|
||||
|
||||
So far, no problem. Whenever an event happens, you put a message on
|
||||
the target window's message queue. Every process has a message
|
||||
queue. If the process queue fills up, the messages back up onto the
|
||||
system queue.
|
||||
|
||||
This is the first cause of apps hanging the GUI. If an app doesn't
|
||||
handle messages and they back up into the system queue, other apps
|
||||
can't get any more messages. The reason is that the next message in
|
||||
line can't go anywhere, and the system won't skip over it.
|
||||
|
||||
This can be fixed by making apps have bigger private message queues.
|
||||
The SIQ fix does this. PMQSIZE does this for systems without the SIQ
|
||||
fix. Applications can also request large queues on their own.
|
||||
|
||||
Another source of the problem, however, happens when you include
|
||||
keyboard events. When you press a key, there's no easy way to know
|
||||
what window the keystroke message should be delivered to.
|
||||
|
||||
Most windowing systems use a concept known as "focus". The window
|
||||
with focus gets all incoming keyboard messages. Focus can be changed
|
||||
from window to window by apps or by users clicking on winodws.
|
||||
|
||||
This is the second source of the problem. Suppose window A has focus.
|
||||
You click on window B and start typing before the window gets focus.
|
||||
Where should the keystrokes go? On the one hand, they should go to A
|
||||
until the focus actually changes to B. On the other hand, you
|
||||
probably want the keystrokes to go to B, since you clicked there
|
||||
first.
|
||||
|
||||
OS/2's solution is that when a focus-changing event happens (like
|
||||
clicking on a window), OS/2 holds all messages in the system queue
|
||||
until the focus change actually happens. This way, subsequent
|
||||
keystrokes go to the window you clicked on, even if it takes a while
|
||||
for that window to get focus.
|
||||
|
||||
The downside is that if the window takes a real long time to get focus
|
||||
(maybe it's not handling events, or maybe the window losing focus
|
||||
isn't handling events), everything backs up in the system queue and
|
||||
the system appears hung.
|
||||
|
||||
There are a few solutions to this problem.
|
||||
|
||||
One is to make focus policy asynchronous. That is, focus changing has
|
||||
absolutely nothing to do with the keyboard. If you click on a window
|
||||
and start typing before the focus actually changes, the keystrokes go
|
||||
to the first window until focus changes, then they go to the second.
|
||||
This is what X-windows does.
|
||||
|
||||
Another is what NT does. When focus changes, keyboard events are held
|
||||
in the system message queue, but other events are allowed through.
|
||||
This is "asynchronous" because the messages in the system queue are
|
||||
delivered to the application queues in a different order from that
|
||||
with which they were posted. If a bad app won't handle the "lose
|
||||
focus" message, it's of no consequence - the app receiving focus will
|
||||
get its "gain focus" message, and the keystrokes will go to it.
|
||||
|
||||
The NT solution also takes care of the application queue filling up
|
||||
problem. Since the system delivers messages asynchronously, messages
|
||||
waiting in the system queue will just sit there and the rest of the
|
||||
messages will be delivered to their apps.
|
||||
|
||||
The OS/2 SIQ solution is this: When a focus-changing event happens,
|
||||
in addition to blocking further messages from the application queues,
|
||||
a timer is started. When the timer goes off, if the focus change has
|
||||
not yet happened, the bad app has its focus taken away and all
|
||||
messages targetted at that window are skipped. When the bad app
|
||||
finally handles the focus change message, OS/2 will detect this and
|
||||
stop skipping its messages.
|
||||
|
||||
|
||||
As for the pros and cons:
|
||||
|
||||
The X-windows solution is probably the easiest. The problem is that
|
||||
users generally don't like having to wait for the focus to change
|
||||
before they start typing. On many occasions, you can type and the
|
||||
characters end up in the wrong window because something (usually heavy
|
||||
system load) is preventing the focus change from happening in a timely
|
||||
manner.
|
||||
|
||||
The NT solution seems pretty nice, but making the system message queue
|
||||
asynchronous can cause similar problems to the X-windows problem.
|
||||
Since messages can be delivered out of order, programs must not assume
|
||||
that two messages posted in a particular order will be delivered in
|
||||
that same order. This can break legacy apps, but since Win32 always
|
||||
had an asynchronous queue, it is fair to simply tell app designers
|
||||
"don't do that". It's harder to tell app designers something like
|
||||
that on OS/2 - they'll complain "you changed the rules and our apps
|
||||
are breaking."
|
||||
|
||||
The OS/2 solution's problem is that nothing happens until you try to
|
||||
change window focus, and then wait for the timeout. Until then, the
|
||||
bad app is not detected and nothing is done." (by David Charlap)
|
||||
|
||||
|
||||
b) Intertask/interthread SendMessage. The system has to inform the
|
||||
target queue about the forthcoming message, then it has to
|
||||
carry out the context switch and wait until the result is
|
||||
available. In Win16 it is done by putting necessary parameters
|
||||
into the queue structure and do a DirectedYield() call.
|
||||
However, in Win32 there could be several messages pending sent
|
||||
by preemptively executing threads, and in this case SendMessage
|
||||
has to build some sort of message queue for sent
|
||||
messages. Another issue is what to do with messages sent to the
|
||||
sender when it is blocked inside its own SendMessage. At this
|
||||
point Wine does not address any of these problems.
|
|
@ -13,7 +13,6 @@
|
|||
extern DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
||||
|
||||
/* message.c */
|
||||
extern BOOL MSG_GetHardwareMessage( LPMSG16 msg );
|
||||
extern BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner,
|
||||
short code, WORD flags, BOOL sendIdle );
|
||||
|
||||
|
@ -21,13 +20,16 @@ extern BOOL MSG_InternalGetMessage( SEGPTR msg, HWND hwnd, HWND hwndOwner,
|
|||
extern void TIMER_RemoveWindowTimers( HWND hwnd );
|
||||
extern void TIMER_RemoveQueueTimers( HQUEUE hqueue );
|
||||
extern void TIMER_SwitchQueue( HQUEUE hOldQueue, HQUEUE hNewQueue );
|
||||
extern LONG TIMER_GetNextExp(void);
|
||||
extern LONG TIMER_GetNextExpiration(void);
|
||||
extern void TIMER_ExpireTimers(void);
|
||||
extern BOOL TIMER_GetTimerMsg( MSG16 *msg, HWND hwnd,
|
||||
HQUEUE hQueue, BOOL remove );
|
||||
|
||||
/* event.c */
|
||||
extern BOOL EVENT_WaitXEvent( LONG maxWait );
|
||||
extern BOOL EVENT_WaitXEvent( BOOL sleep );
|
||||
extern void EVENT_Synchronize(void);
|
||||
extern void EVENT_ProcessEvent( XEvent *event );
|
||||
extern void EVENT_RegisterWindow( Window w, HWND hwnd );
|
||||
extern void EVENT_RegisterWindow( WND *pWnd );
|
||||
extern void EVENT_DummyMotionNotify(void);
|
||||
|
||||
#endif /* __WINE_MESSAGE_H */
|
||||
|
|
|
@ -32,7 +32,7 @@ typedef struct tagMESSAGEQUEUE
|
|||
WORD queueSize; /* 0c Size of the queue */
|
||||
DWORD GetMessageTimeVal WINE_PACKED; /* 0e Value for GetMessageTime */
|
||||
DWORD GetMessagePosVal WINE_PACKED; /* 12 Value for GetMessagePos */
|
||||
WORD reserved1; /* 16 Unknown */
|
||||
HQUEUE self; /* 16 Handle to self (was: reserved) */
|
||||
DWORD GetMessageExtraInfoVal; /* 18 Value for GetMessageExtraInfo */
|
||||
WORD reserved2; /* 1c Unknown */
|
||||
LPARAM lParam WINE_PACKED; /* 1e Next 4 values set by SendMessage */
|
||||
|
@ -75,6 +75,7 @@ extern void QUEUE_DumpQueue( HQUEUE hQueue );
|
|||
extern void QUEUE_WalkQueues(void);
|
||||
extern MESSAGEQUEUE *QUEUE_GetSysQueue(void);
|
||||
extern void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
||||
extern void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit );
|
||||
extern void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue );
|
||||
extern void QUEUE_WaitBits( WORD bits );
|
||||
extern void QUEUE_IncPaintCount( HQUEUE hQueue );
|
||||
|
|
|
@ -469,6 +469,7 @@ DECL_WINELIB_TYPE(LPNCCALCSIZE_PARAMS);
|
|||
|
||||
/* CallMsgFilter() values */
|
||||
#define MSGF_DIALOGBOX 0
|
||||
#define MSGF_MESSAGEBOX 1
|
||||
#define MSGF_MENU 2
|
||||
#define MSGF_MOVE 3
|
||||
#define MSGF_SIZE 4
|
||||
|
|
|
@ -84,7 +84,7 @@ WNDPROC MODULE_GetWndProcEntry16( char *name )
|
|||
MAP_STR_TO_PROC("ColorDlgProc",ColorDlgProc);
|
||||
MAP_STR_TO_PROC("ComboBoxWndProc",ComboBoxWndProc);
|
||||
MAP_STR_TO_PROC("ComboLBoxWndProc",ComboLBoxWndProc);
|
||||
MAP_STR_TO_PROC("DefDlgProc",DefDlgProc);
|
||||
MAP_STR_TO_PROC("DefDlgProc",DefDlgProc16);
|
||||
MAP_STR_TO_PROC("EditWndProc",EditWndProc);
|
||||
MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc);
|
||||
MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc);
|
||||
|
|
|
@ -677,7 +677,7 @@ void TASK_Reschedule(void)
|
|||
|
||||
/* Flush any X events that happened in the meantime */
|
||||
|
||||
EVENT_WaitXEvent( 0 );
|
||||
EVENT_WaitXEvent( FALSE );
|
||||
|
||||
/* Find a task to yield to */
|
||||
|
||||
|
@ -707,7 +707,7 @@ void TASK_Reschedule(void)
|
|||
|
||||
/* No task found, wait for some events to come in */
|
||||
|
||||
EVENT_WaitXEvent( TIMER_GetNextExp() );
|
||||
EVENT_WaitXEvent( TRUE );
|
||||
}
|
||||
|
||||
if (hTask == hCurrentTask) return; /* Nothing to do */
|
||||
|
|
|
@ -1005,6 +1005,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
|
|||
SetLastError( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
HEAP_ShrinkBlock( subheap, pArena, size );
|
||||
}
|
||||
else /* Do it the hard way */
|
||||
{
|
||||
|
@ -1029,6 +1030,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
|
|||
+ sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
|
||||
pInUse->threadId = GetCurrentTask();
|
||||
pInUse->magic = ARENA_INUSE_MAGIC;
|
||||
HEAP_ShrinkBlock( subheap, pInUse, size );
|
||||
memcpy( pInUse + 1, pArena + 1, oldSize );
|
||||
|
||||
/* Free the previous block */
|
||||
|
@ -1038,11 +1040,7 @@ LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
|
|||
pArena = pInUse;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Shrink the block */
|
||||
|
||||
HEAP_ShrinkBlock( subheap, pArena, size );
|
||||
else HEAP_ShrinkBlock( subheap, pArena, size ); /* Shrink the block */
|
||||
|
||||
/* Clear the extra bytes if needed */
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ BOOL CLIPBOARD_RequestXSelection()
|
|||
WIN_GetXWindow(hWnd),CurrentTime);
|
||||
|
||||
/* TODO: need time-out for broken clients */
|
||||
while(wait_for_selection) EVENT_WaitXEvent(-1);
|
||||
while(wait_for_selection) EVENT_WaitXEvent( TRUE );
|
||||
|
||||
return (BOOL)ClipFormats[0].wDataPresent;
|
||||
}
|
||||
|
|
38
misc/shell.c
38
misc/shell.c
|
@ -501,8 +501,8 @@ HICON InternalExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, UINT nIco
|
|||
|
||||
for( i = nIconIndex; i < nIconIndex + n; i++ )
|
||||
{
|
||||
hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + (i - nIconIndex),
|
||||
*(WORD*)pData );
|
||||
hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
|
||||
*(WORD*)pData );
|
||||
RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
|
||||
GlobalFree16(hIcon);
|
||||
}
|
||||
|
@ -547,18 +547,40 @@ HICON ExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, WORD nIconIndex)
|
|||
|
||||
/*************************************************************************
|
||||
* ExtractAssociatedIcon [SHELL.36]
|
||||
*
|
||||
* Return icon for given file (either from file itself or from associated
|
||||
* executable) and patch parameters if needed.
|
||||
*/
|
||||
HICON ExtractAssociatedIcon(HINSTANCE hInst,LPSTR lpIconPath, LPWORD lpiIcon)
|
||||
{
|
||||
HICON hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
|
||||
|
||||
/* MAKEINTRESOURCE(2) seems to be "default" icon according to Progman
|
||||
*
|
||||
* For data files it probably should call FindExecutable and load
|
||||
* icon from there. As of now FindExecutable is empty stub.
|
||||
*/
|
||||
if( hIcon < 2 )
|
||||
{
|
||||
|
||||
if( hIcon < 2 ) hIcon = LoadIcon( hInst, MAKEINTRESOURCE(2));
|
||||
if( hIcon == 1 ) /* no icons found in given file */
|
||||
{
|
||||
char tempPath[0x80];
|
||||
UINT uRet = FindExecutable(lpIconPath,NULL,tempPath);
|
||||
|
||||
if( uRet > 32 && tempPath[0] )
|
||||
{
|
||||
strcpy(lpIconPath,tempPath);
|
||||
hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
|
||||
|
||||
if( hIcon > 2 ) return hIcon;
|
||||
}
|
||||
else hIcon = 0;
|
||||
}
|
||||
|
||||
if( hIcon == 1 )
|
||||
*lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
|
||||
else
|
||||
*lpiIcon = 6; /* generic icon - found nothing */
|
||||
|
||||
GetModuleFileName(hInst, lpIconPath, 0x80);
|
||||
hIcon = LoadIcon( hInst, MAKEINTRESOURCE(*lpiIcon));
|
||||
}
|
||||
|
||||
return hIcon;
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ INT16 wvsnprintf16( LPSTR buffer, UINT16 maxlen, LPCSTR spec, LPCVOID args )
|
|||
{
|
||||
case WPR_CHAR:
|
||||
cur_arg = (DWORD)*(CHAR *)args;
|
||||
args = (CHAR *)args + 1;
|
||||
args = (WORD *)args + 1;
|
||||
break;
|
||||
case WPR_STRING:
|
||||
cur_arg = (DWORD)PTR_SEG_TO_LIN( *(SEGPTR *)args );
|
||||
|
|
|
@ -621,9 +621,9 @@ BOOL DeleteDC( HDC hdc )
|
|||
SelectObject( hdc, STOCK_WHITE_BRUSH );
|
||||
SelectObject( hdc, STOCK_SYSTEM_FONT );
|
||||
XFreeGC( display, dc->u.x.gc );
|
||||
if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
|
||||
}
|
||||
|
||||
if (dc->w.flags & DC_MEMORY) DeleteObject( dc->w.hFirstBitmap );
|
||||
if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
|
||||
if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
|
||||
if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
|
||||
|
|
|
@ -200,7 +200,7 @@ static BOOL CLASS_FreeClass( CLASS *classPtr )
|
|||
if (classPtr->hbrBackground) DeleteObject( classPtr->hbrBackground );
|
||||
GlobalDeleteAtom( classPtr->atomName );
|
||||
CLASS_SetMenuNameA( classPtr, NULL );
|
||||
CLASS_SetWndProc( classPtr, (WNDPROC16)0, WIN_PROC_16 );
|
||||
CLASS_SetWndProc( classPtr, (HANDLE32)0, WIN_PROC_16 );
|
||||
HeapFree( SystemHeap, 0, classPtr );
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -159,9 +159,8 @@ BOOL DCE_InvalidateDCE(WND* wndScope, RECT16* pRectUpdate)
|
|||
|
||||
dprintf_dc(stddeb,"\tgot hwnd %04x\n", wndCurrent->hwndSelf);
|
||||
|
||||
if( wndCurrent->parent != wndScope )
|
||||
MapWindowPoints16(wndCurrent->parent->hwndSelf, wndScope->hwndSelf,
|
||||
(LPPOINT16)&wndRect, 2);
|
||||
MapWindowPoints16(wndCurrent->parent->hwndSelf, wndScope->hwndSelf,
|
||||
(LPPOINT16)&wndRect, 2);
|
||||
if( IntersectRect16(&wndRect,&wndRect,pRectUpdate) )
|
||||
SetHookFlags(dce->hDC, DCHF_INVALIDATEVISRGN);
|
||||
break;
|
||||
|
|
169
windows/event.c
169
windows/event.c
|
@ -25,6 +25,7 @@
|
|||
#include "class.h"
|
||||
#include "clipboard.h"
|
||||
#include "debugger.h"
|
||||
#include "message.h"
|
||||
#include "module.h"
|
||||
#include "options.h"
|
||||
#include "queue.h"
|
||||
|
@ -35,19 +36,6 @@
|
|||
#include "dde_proc.h"
|
||||
|
||||
|
||||
#ifdef ndef
|
||||
#ifndef FamilyAmoeba
|
||||
typedef char *XPointer;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef WHO_NEEDS_DIRTY_HACKS
|
||||
#ifdef sparc
|
||||
/* Dirty hack to compile with Sun's OpenWindows */
|
||||
typedef char *XPointer;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NB_BUTTONS 3 /* Windows can handle 3 buttons */
|
||||
|
||||
/* X context to associate a hwnd to an X window */
|
||||
|
@ -152,13 +140,13 @@ static void EVENT_ButtonRelease( XButtonEvent *event );
|
|||
static void EVENT_MotionNotify( XMotionEvent *event );
|
||||
static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
|
||||
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
|
||||
static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
|
||||
static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event );
|
||||
static void EVENT_Expose( WND *pWnd, XExposeEvent *event );
|
||||
static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event );
|
||||
static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
|
||||
static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event);
|
||||
static void EVENT_SelectionNotify( HWND hwnd, XSelectionEvent *event);
|
||||
static void EVENT_SelectionClear( HWND hwnd, XSelectionClearEvent *event);
|
||||
static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
|
||||
static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event);
|
||||
static void EVENT_SelectionNotify( XSelectionEvent *event);
|
||||
static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event);
|
||||
static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event );
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -168,14 +156,14 @@ static void EVENT_ClientMessage( HWND hwnd, XClientMessageEvent *event );
|
|||
*/
|
||||
void EVENT_ProcessEvent( XEvent *event )
|
||||
{
|
||||
HWND hwnd;
|
||||
XPointer ptr;
|
||||
WND *pWnd;
|
||||
|
||||
XFindContext( display, ((XAnyEvent *)event)->window, winContext, &ptr );
|
||||
hwnd = (HWND) (int)ptr;
|
||||
if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
|
||||
(char **)&pWnd ) != 0)
|
||||
return; /* Not for a registered window */
|
||||
|
||||
dprintf_event(stddeb, "Got event %s for hwnd %04x\n",
|
||||
event_names[event->type], hwnd );
|
||||
dprintf_event( stddeb, "Got event %s for hwnd %04x\n",
|
||||
event_names[event->type], pWnd->hwndSelf );
|
||||
|
||||
switch(event->type)
|
||||
{
|
||||
|
@ -207,46 +195,47 @@ void EVENT_ProcessEvent( XEvent *event )
|
|||
break;
|
||||
|
||||
case FocusIn:
|
||||
EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
|
||||
EVENT_FocusIn( pWnd->hwndSelf, (XFocusChangeEvent*)event );
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
EVENT_FocusOut( hwnd, (XFocusChangeEvent*)event );
|
||||
EVENT_FocusOut( pWnd->hwndSelf, (XFocusChangeEvent*)event );
|
||||
break;
|
||||
|
||||
case Expose:
|
||||
EVENT_Expose( hwnd, (XExposeEvent*)event );
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
|
||||
break;
|
||||
|
||||
case SelectionRequest:
|
||||
EVENT_SelectionRequest( hwnd, (XSelectionRequestEvent*)event );
|
||||
break;
|
||||
|
||||
case SelectionNotify:
|
||||
EVENT_SelectionNotify( hwnd, (XSelectionEvent*)event );
|
||||
break;
|
||||
|
||||
case SelectionClear:
|
||||
EVENT_SelectionClear( hwnd, (XSelectionClearEvent*) event );
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
EVENT_ClientMessage( hwnd, (XClientMessageEvent *) event );
|
||||
EVENT_Expose( pWnd, (XExposeEvent *)event );
|
||||
break;
|
||||
|
||||
case GraphicsExpose:
|
||||
EVENT_GraphicsExpose( hwnd, (XGraphicsExposeEvent *) event );
|
||||
EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
|
||||
break;
|
||||
|
||||
case ConfigureNotify:
|
||||
EVENT_ConfigureNotify( pWnd->hwndSelf, (XConfigureEvent*)event );
|
||||
break;
|
||||
|
||||
case SelectionRequest:
|
||||
EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
|
||||
break;
|
||||
|
||||
case SelectionNotify:
|
||||
EVENT_SelectionNotify( (XSelectionEvent *)event );
|
||||
break;
|
||||
|
||||
case SelectionClear:
|
||||
EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
|
||||
break;
|
||||
|
||||
case ClientMessage:
|
||||
EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event );
|
||||
break;
|
||||
|
||||
case NoExpose:
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintf_event(stddeb, "Unprocessed event %s for hwnd %04x\n",
|
||||
event_names[event->type], hwnd );
|
||||
event_names[event->type], pWnd->hwndSelf );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -257,29 +246,31 @@ void EVENT_ProcessEvent( XEvent *event )
|
|||
*
|
||||
* Associate an X window to a HWND.
|
||||
*/
|
||||
void EVENT_RegisterWindow( Window w, HWND hwnd )
|
||||
void EVENT_RegisterWindow( WND *pWnd )
|
||||
{
|
||||
if (!winContext) winContext = XUniqueContext();
|
||||
XSaveContext( display, w, winContext, (XPointer)(int)hwnd );
|
||||
XSaveContext( display, pWnd->window, winContext, (char *)pWnd );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_WaitXEvent
|
||||
*
|
||||
* Wait for an X event, but at most maxWait milliseconds (-1 for no timeout).
|
||||
* Wait for an X event, optionally sleeping until one arrives.
|
||||
* Return TRUE if an event is pending, FALSE on timeout or error
|
||||
* (for instance lost connection with the server).
|
||||
*/
|
||||
BOOL EVENT_WaitXEvent( LONG maxWait )
|
||||
BOOL EVENT_WaitXEvent( BOOL sleep )
|
||||
{
|
||||
fd_set read_set;
|
||||
struct timeval timeout;
|
||||
XEvent event;
|
||||
int fd = ConnectionNumber(display);
|
||||
|
||||
if (!XPending(display) && (maxWait != -1))
|
||||
if (!XPending(display))
|
||||
{
|
||||
LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0;
|
||||
|
||||
FD_ZERO( &read_set );
|
||||
FD_SET( fd, &read_set );
|
||||
|
||||
|
@ -295,18 +286,23 @@ BOOL EVENT_WaitXEvent( LONG maxWait )
|
|||
;
|
||||
return TRUE;
|
||||
}
|
||||
stop_wait_op= STOP_WAIT_X;
|
||||
/* The code up to the next "stop_wait_op= CONT" must be reentrant */
|
||||
stop_wait_op = STOP_WAIT_X;
|
||||
/* The code up to the next "stop_wait_op = CONT" must be reentrant */
|
||||
if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
|
||||
!XPending(display)) {
|
||||
stop_wait_op= CONT;
|
||||
!XPending(display))
|
||||
{
|
||||
stop_wait_op = CONT;
|
||||
TIMER_ExpireTimers();
|
||||
return FALSE;
|
||||
} else {
|
||||
stop_wait_op= CONT;
|
||||
}
|
||||
else stop_wait_op = CONT;
|
||||
#else /* CONFIG_IPC */
|
||||
if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
|
||||
return FALSE; /* Timeout or error */
|
||||
{
|
||||
/* Timeout or error */
|
||||
TIMER_ExpireTimers();
|
||||
return FALSE;
|
||||
}
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
}
|
||||
|
@ -371,19 +367,17 @@ static WORD EVENT_XStateToKeyState( int state )
|
|||
/***********************************************************************
|
||||
* EVENT_Expose
|
||||
*/
|
||||
static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
|
||||
static void EVENT_Expose( WND *pWnd, XExposeEvent *event )
|
||||
{
|
||||
RECT32 rect;
|
||||
WND * wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (!wndPtr) return;
|
||||
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
|
||||
rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
|
||||
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
|
||||
rect.right = rect.left + event->width;
|
||||
rect.bottom = rect.top + event->height;
|
||||
|
||||
RedrawWindow32( hwnd, &rect, 0,
|
||||
RedrawWindow32( pWnd->hwndSelf, &rect, 0,
|
||||
RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
|
||||
(event->count ? 0 : RDW_ERASENOW) );
|
||||
}
|
||||
|
@ -391,22 +385,21 @@ static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
|
|||
|
||||
/***********************************************************************
|
||||
* EVENT_GraphicsExpose
|
||||
*
|
||||
* This is needed when scrolling area is partially obscured
|
||||
* by non-Wine X window.
|
||||
*/
|
||||
static void EVENT_GraphicsExpose( HWND hwnd, XGraphicsExposeEvent *event )
|
||||
static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
|
||||
{
|
||||
RECT16 rect;
|
||||
WND * wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (!wndPtr) return;
|
||||
RECT32 rect;
|
||||
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
|
||||
rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
|
||||
/* Make position relative to client area instead of window */
|
||||
rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left);
|
||||
rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top);
|
||||
rect.right = rect.left + event->width;
|
||||
rect.bottom = rect.top + event->height;
|
||||
|
||||
RedrawWindow16( hwnd, &rect, 0,
|
||||
RedrawWindow32( pWnd->hwndSelf, &rect, 0,
|
||||
RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
|
||||
(event->count ? 0 : RDW_ERASENOW) );
|
||||
}
|
||||
|
@ -712,7 +705,7 @@ static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
|
|||
/***********************************************************************
|
||||
* EVENT_SelectionRequest
|
||||
*/
|
||||
static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
|
||||
static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
|
||||
{
|
||||
XSelectionEvent result;
|
||||
Atom rprop = None;
|
||||
|
@ -731,7 +724,7 @@ static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
|
|||
else if(!CLIPBOARD_IsPresent(CF_TEXT)) rprop = None;
|
||||
else{
|
||||
/* Don't worry if we can't open */
|
||||
BOOL couldOpen=OpenClipboard(hwnd);
|
||||
BOOL couldOpen=OpenClipboard( pWnd->hwndSelf );
|
||||
hText=GetClipboardData(CF_TEXT);
|
||||
text=GlobalLock16(hText);
|
||||
XChangeProperty(display,request,rprop,XA_STRING,
|
||||
|
@ -759,28 +752,28 @@ static void EVENT_SelectionRequest( HWND hwnd, XSelectionRequestEvent *event )
|
|||
/***********************************************************************
|
||||
* EVENT_SelectionNotify
|
||||
*/
|
||||
static void EVENT_SelectionNotify(HWND hwnd, XSelectionEvent *event)
|
||||
static void EVENT_SelectionNotify( XSelectionEvent *event )
|
||||
{
|
||||
if(event->selection!=XA_PRIMARY)return;
|
||||
if(event->target!=XA_STRING)CLIPBOARD_ReadSelection(0,None);
|
||||
CLIPBOARD_ReadSelection(event->requestor,event->property);
|
||||
if (event->selection != XA_PRIMARY) return;
|
||||
if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None );
|
||||
CLIPBOARD_ReadSelection( event->requestor, event->property );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* EVENT_SelectionClear
|
||||
*/
|
||||
static void EVENT_SelectionClear(HWND hwnd, XSelectionClearEvent *event)
|
||||
static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event )
|
||||
{
|
||||
if(event->selection!=XA_PRIMARY)return;
|
||||
CLIPBOARD_ReleaseSelection(hwnd);
|
||||
if (event->selection != XA_PRIMARY) return;
|
||||
CLIPBOARD_ReleaseSelection( pWnd->hwndSelf );
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* EVENT_ClientMessage
|
||||
*/
|
||||
static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
|
||||
static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event )
|
||||
{
|
||||
static Atom wmProtocols = None;
|
||||
static Atom wmDeleteWindow = None;
|
||||
|
@ -796,7 +789,7 @@ static void EVENT_ClientMessage (HWND hwnd, XClientMessageEvent *event )
|
|||
dprintf_event( stddeb, "unrecognized ClientMessage\n" );
|
||||
return;
|
||||
}
|
||||
SendMessage16( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
|
||||
SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ BOOL16 DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count )
|
|||
{
|
||||
points->x = XDPTOLP( dc, points->x );
|
||||
points->y = YDPTOLP( dc, points->y );
|
||||
points++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -65,6 +66,7 @@ BOOL32 DPtoLP32( HDC32 hdc, LPPOINT32 points, INT32 count )
|
|||
{
|
||||
points->x = XDPTOLP( dc, points->x );
|
||||
points->y = YDPTOLP( dc, points->y );
|
||||
points++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -82,6 +84,7 @@ BOOL16 LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count )
|
|||
{
|
||||
points->x = XLPTODP( dc, points->x );
|
||||
points->y = YLPTODP( dc, points->y );
|
||||
points++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -99,6 +102,7 @@ BOOL32 LPtoDP32( HDC32 hdc, LPPOINT32 points, INT32 count )
|
|||
{
|
||||
points->x = XLPTODP( dc, points->x );
|
||||
points->y = YLPTODP( dc, points->y );
|
||||
points++;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -29,10 +29,7 @@
|
|||
extern BYTE* KeyStateTable; /* event.c */
|
||||
extern WPARAM lastEventChar; /* event.c */
|
||||
|
||||
extern BOOL TIMER_CheckTimer( LONG *next, MSG16 *msg,
|
||||
HWND hwnd, BOOL remove ); /* timer.c */
|
||||
|
||||
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
||||
DWORD MSG_WineStartTicks; /* Ticks at Wine startup */
|
||||
|
||||
static WORD doubleClickSpeed = 452;
|
||||
|
||||
|
@ -68,9 +65,8 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
|
|||
|
||||
/* Find the window */
|
||||
|
||||
if (GetCapture())
|
||||
if ((msg->hwnd = GetCapture()) != 0)
|
||||
{
|
||||
msg->hwnd = GetCapture();
|
||||
ScreenToClient16( msg->hwnd, &pt );
|
||||
msg->lParam = MAKELONG( pt.x, pt.y );
|
||||
/* No need to further process the message */
|
||||
|
@ -80,6 +76,16 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
|
|||
}
|
||||
|
||||
hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
|
||||
if (pWnd->hmemTaskQ != GetTaskQueue(0))
|
||||
{
|
||||
/* Not for the current task */
|
||||
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
|
||||
if (queue) QUEUE_ClearWakeBit( queue, QS_MOUSE );
|
||||
/* Wake up the other task */
|
||||
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_MOUSE );
|
||||
return FALSE;
|
||||
}
|
||||
msg->hwnd = pWnd->hwndSelf;
|
||||
if ((hittest != HTERROR) && mouseClick)
|
||||
{
|
||||
|
@ -172,6 +178,8 @@ static BOOL MSG_TranslateMouseMsg( MSG16 *msg, BOOL remove )
|
|||
*/
|
||||
static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
|
||||
{
|
||||
WND *pWnd;
|
||||
|
||||
/* Should check Ctrl-Esc and PrintScreen here */
|
||||
|
||||
msg->hwnd = GetFocus();
|
||||
|
@ -185,6 +193,17 @@ static BOOL MSG_TranslateKeyboardMsg( MSG16 *msg, BOOL remove )
|
|||
if( msg->message < WM_SYSKEYDOWN )
|
||||
msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
|
||||
}
|
||||
pWnd = WIN_FindWndPtr( msg->hwnd );
|
||||
if (pWnd && (pWnd->hmemTaskQ != GetTaskQueue(0)))
|
||||
{
|
||||
/* Not for the current task */
|
||||
MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) );
|
||||
if (queue) QUEUE_ClearWakeBit( queue, QS_KEY );
|
||||
/* Wake up the other task */
|
||||
queue = (MESSAGEQUEUE *)GlobalLock16( pWnd->hmemTaskQ );
|
||||
if (queue) QUEUE_SetWakeBit( queue, QS_KEY );
|
||||
return FALSE;
|
||||
}
|
||||
return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
|
||||
msg->wParam, msg->lParam );
|
||||
}
|
||||
|
@ -202,7 +221,7 @@ static BOOL MSG_PeekHardwareMsg( MSG16 *msg, HWND hwnd, WORD first, WORD last,
|
|||
int i, pos = sysMsgQueue->nextMessage;
|
||||
|
||||
/* If the queue is empty, attempt to fill it */
|
||||
if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( 0 );
|
||||
if (!sysMsgQueue->msgCount && XPending(display)) EVENT_WaitXEvent( FALSE );
|
||||
|
||||
for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
|
||||
{
|
||||
|
@ -266,38 +285,6 @@ WORD GetDoubleClickTime()
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MSG_GetHardwareMessage
|
||||
*
|
||||
* Like GetMessage(), but only return mouse and keyboard events.
|
||||
* Used internally for window moving and resizing. Mouse messages
|
||||
* are not translated.
|
||||
* Warning: msg->hwnd is always 0.
|
||||
*/
|
||||
BOOL MSG_GetHardwareMessage( LPMSG16 msg )
|
||||
{
|
||||
#if 0
|
||||
int pos;
|
||||
XEvent event;
|
||||
MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
|
||||
|
||||
while(1)
|
||||
{
|
||||
if ((pos = QUEUE_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
|
||||
{
|
||||
*msg = sysMsgQueue->messages[pos].msg;
|
||||
QUEUE_RemoveMsg( sysMsgQueue, pos );
|
||||
break;
|
||||
}
|
||||
XNextEvent( display, &event );
|
||||
EVENT_ProcessEvent( &event );
|
||||
}
|
||||
#endif
|
||||
MSG_PeekMessage( msg, 0, WM_KEYFIRST, WM_MOUSELAST, PM_REMOVE, 0 );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* MSG_SendMessage
|
||||
*
|
||||
|
@ -381,7 +368,6 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
|
|||
int pos, mask;
|
||||
MESSAGEQUEUE *msgQueue;
|
||||
HQUEUE hQueue;
|
||||
LONG nextExp; /* Next timer expiration time */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
DDE_TestDDE(hwnd); /* do we have dde handling in the window ?*/
|
||||
|
@ -490,10 +476,8 @@ static BOOL MSG_PeekMessage( LPMSG16 msg, HWND hwnd, WORD first, WORD last,
|
|||
}
|
||||
if ((msgQueue->wakeBits & mask) & QS_TIMER)
|
||||
{
|
||||
if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
|
||||
break; /* Got a timer msg */
|
||||
if (TIMER_GetTimerMsg(msg, hwnd, hQueue, flags & PM_REMOVE)) break;
|
||||
}
|
||||
else nextExp = -1; /* No timeout needed */
|
||||
|
||||
if (peek)
|
||||
{
|
||||
|
@ -792,24 +776,7 @@ LRESULT SendMessage32W(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
|
|||
*/
|
||||
void WaitMessage( void )
|
||||
{
|
||||
MSG16 msg;
|
||||
MESSAGEQUEUE *queue;
|
||||
LONG nextExp = -1; /* Next timer expiration time */
|
||||
|
||||
#ifdef CONFIG_IPC
|
||||
DDE_GetRemoteMessage();
|
||||
#endif /* CONFIG_IPC */
|
||||
|
||||
if (!(queue = (MESSAGEQUEUE *)GlobalLock16( GetTaskQueue(0) ))) return;
|
||||
if ((queue->wPostQMsg) ||
|
||||
(queue->wakeBits & (QS_SENDMESSAGE | QS_PAINT)) ||
|
||||
(queue->msgCount) || (QUEUE_GetSysQueue()->msgCount) )
|
||||
return;
|
||||
if ((queue->wakeBits & QS_TIMER) &&
|
||||
TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
|
||||
return;
|
||||
/* FIXME: (dde) must check DDE & X-events simultaneously */
|
||||
EVENT_WaitXEvent( nextExp );
|
||||
QUEUE_WaitBits( QS_ALLINPUT );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "menu.h"
|
||||
#include "winpos.h"
|
||||
#include "scroll.h"
|
||||
#include "stackframe.h"
|
||||
#include "nonclient.h"
|
||||
#include "graphics.h"
|
||||
#include "queue.h"
|
||||
|
@ -907,7 +908,8 @@ static LONG NC_StartSizeMove( HWND hwnd, WPARAM wParam, POINT16 *capturePoint )
|
|||
SetCapture(hwnd);
|
||||
while(!hittest)
|
||||
{
|
||||
MSG_GetHardwareMessage( &msg );
|
||||
MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
|
||||
PM_REMOVE, FALSE );
|
||||
switch(msg.message)
|
||||
{
|
||||
case WM_MOUSEMOVE:
|
||||
|
@ -1046,7 +1048,8 @@ static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT16 pt )
|
|||
{
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
MSG_GetHardwareMessage( &msg );
|
||||
MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, MSGF_SIZE,
|
||||
PM_REMOVE, FALSE );
|
||||
|
||||
/* Exit on button-up, Return, or Esc */
|
||||
if ((msg.message == WM_LBUTTONUP) ||
|
||||
|
@ -1148,7 +1151,7 @@ static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
|
|||
do
|
||||
{
|
||||
BOOL oldstate = pressed;
|
||||
MSG_GetHardwareMessage( &msg );
|
||||
MSG_InternalGetMessage( MAKE_SEGPTR(&msg), 0, 0, 0, PM_REMOVE, FALSE );
|
||||
|
||||
pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
|
||||
if (pressed != oldstate)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
static HQUEUE hFirstQueue = 0;
|
||||
static HQUEUE hmemSysMsgQueue = 0;
|
||||
static MESSAGEQUEUE *pMouseQueue = NULL; /* Queue for last mouse message */
|
||||
static MESSAGEQUEUE *pKbdQueue = NULL; /* Queue for last kbd message */
|
||||
static HQUEUE hDoomedQueue = 0;
|
||||
static MESSAGEQUEUE *sysMsgQueue = NULL;
|
||||
|
||||
|
@ -111,6 +113,7 @@ static HQUEUE QUEUE_CreateMsgQueue( int size )
|
|||
if (!(hQueue = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, queueSize )))
|
||||
return 0;
|
||||
msgQueue = (MESSAGEQUEUE *) GlobalLock16( hQueue );
|
||||
msgQueue->self = hQueue;
|
||||
msgQueue->msgSize = sizeof(QMSG);
|
||||
msgQueue->queueSize = size;
|
||||
msgQueue->wWinVersion = pTask ? pTask->version : 0;
|
||||
|
@ -144,6 +147,7 @@ BOOL QUEUE_DeleteMsgQueue( HQUEUE hQueue )
|
|||
pPrev = &msgQ->next;
|
||||
}
|
||||
if (*pPrev) *pPrev = msgQueue->next;
|
||||
msgQueue->self = 0;
|
||||
GlobalFree16( hQueue );
|
||||
return 1;
|
||||
}
|
||||
|
@ -181,6 +185,8 @@ MESSAGEQUEUE *QUEUE_GetSysQueue(void)
|
|||
*/
|
||||
void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
|
||||
{
|
||||
if (bit & QS_MOUSE) pMouseQueue = queue;
|
||||
if (bit & QS_KEY) pKbdQueue = queue;
|
||||
queue->changeBits |= bit;
|
||||
queue->wakeBits |= bit;
|
||||
if (queue->wakeMask & bit)
|
||||
|
@ -191,6 +197,16 @@ void QUEUE_SetWakeBit( MESSAGEQUEUE *queue, WORD bit )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* QUEUE_ClearWakeBit
|
||||
*/
|
||||
void QUEUE_ClearWakeBit( MESSAGEQUEUE *queue, WORD bit )
|
||||
{
|
||||
queue->changeBits &= ~bit;
|
||||
queue->wakeBits &= ~bit;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* QUEUE_WaitBits
|
||||
*
|
||||
|
@ -233,16 +249,22 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
|
|||
WPARAM wParam;
|
||||
LPARAM lParam;
|
||||
LRESULT result = 0;
|
||||
HQUEUE oldSender;
|
||||
|
||||
printf( "ReceiveMessage\n" );
|
||||
if (!(queue->wakeBits & QS_SENDMESSAGE)) return;
|
||||
if (!(senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask))) return;
|
||||
|
||||
/* Remove sending queue from the list */
|
||||
oldSender = queue->InSendMessageHandle;
|
||||
queue->InSendMessageHandle = queue->hSendingTask;
|
||||
queue->hSendingTask = senderQ->hPrevSendingTask;
|
||||
senderQ->hPrevSendingTask = 0;
|
||||
if (!queue->hSendingTask) queue->wakeBits &= ~QS_SENDMESSAGE;
|
||||
if (!queue->hSendingTask)
|
||||
{
|
||||
queue->wakeBits &= ~QS_SENDMESSAGE;
|
||||
queue->changeBits &= ~QS_SENDMESSAGE;
|
||||
}
|
||||
|
||||
/* Get the parameters from the sending task */
|
||||
hwnd = senderQ->hWnd;
|
||||
|
@ -257,13 +279,21 @@ void QUEUE_ReceiveMessage( MESSAGEQUEUE *queue )
|
|||
|
||||
/* Call the window procedure */
|
||||
/* FIXME: should we use CallWindowProc here? */
|
||||
if (IsWindow( hwnd )) result = SendMessage16( hwnd, msg, wParam, lParam );
|
||||
if (IsWindow( hwnd ))
|
||||
{
|
||||
DWORD extraInfo = queue->GetMessageExtraInfoVal;
|
||||
queue->GetMessageExtraInfoVal = senderQ->GetMessageExtraInfoVal;
|
||||
result = SendMessage16( hwnd, msg, wParam, lParam );
|
||||
queue->GetMessageExtraInfoVal = extraInfo; /* Restore extra info */
|
||||
}
|
||||
|
||||
printf( "ReceiveMessage: wnd proc %04x %04x %04x %08x ret = %08x\n",
|
||||
hwnd, msg, wParam, lParam, result );
|
||||
|
||||
/* Return the result to the sender task */
|
||||
ReplyMessage( result );
|
||||
|
||||
queue->InSendMessageHandle = oldSender;
|
||||
}
|
||||
|
||||
|
||||
|
@ -373,15 +403,18 @@ static void QUEUE_WakeSomeone( UINT message )
|
|||
|
||||
if (!(hwnd = GetSysModalWindow()))
|
||||
{
|
||||
hwnd = (wakeBit == QS_KEY) ? GetFocus() : GetCapture();
|
||||
if (!hwnd) hwnd = GetActiveWindow();
|
||||
if (wakeBit == QS_KEY)
|
||||
{
|
||||
if (!(hwnd = GetFocus())) hwnd = GetActiveWindow();
|
||||
}
|
||||
else hwnd = GetCapture();
|
||||
}
|
||||
if (hwnd)
|
||||
{
|
||||
WND *wndPtr = WIN_FindWndPtr( hwnd );
|
||||
if (wndPtr) queue = (MESSAGEQUEUE *)GlobalLock16( wndPtr->hmemTaskQ );
|
||||
}
|
||||
else
|
||||
else if (!(queue = pMouseQueue))
|
||||
{
|
||||
hQueue = hFirstQueue;
|
||||
while (hQueue)
|
||||
|
|
|
@ -19,7 +19,7 @@ typedef struct tagTIMER
|
|||
WORD id;
|
||||
WORD timeout;
|
||||
struct tagTIMER *next;
|
||||
DWORD expires;
|
||||
DWORD expires; /* Next expiration, or 0 if already expired */
|
||||
FARPROC proc;
|
||||
} TIMER;
|
||||
|
||||
|
@ -70,6 +70,7 @@ static void TIMER_RemoveTimer( TIMER * pTimer )
|
|||
while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next;
|
||||
if (*ppTimer) *ppTimer = pTimer->next;
|
||||
pTimer->next = NULL;
|
||||
if (!pTimer->expires) QUEUE_DecTimerCount( pTimer->hq );
|
||||
}
|
||||
|
||||
|
||||
|
@ -81,7 +82,6 @@ static void TIMER_RemoveTimer( TIMER * pTimer )
|
|||
static void TIMER_ClearTimer( TIMER * pTimer )
|
||||
{
|
||||
TIMER_RemoveTimer( pTimer );
|
||||
QUEUE_DecTimerCount( pTimer->hq );
|
||||
pTimer->hwnd = 0;
|
||||
pTimer->msg = 0;
|
||||
pTimer->id = 0;
|
||||
|
@ -151,44 +151,58 @@ static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime )
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* TIMER_GetNextExp
|
||||
* TIMER_GetNextExpiration
|
||||
*
|
||||
* Return next timer expiration time, or -1 if none.
|
||||
*/
|
||||
LONG TIMER_GetNextExp(void)
|
||||
LONG TIMER_GetNextExpiration(void)
|
||||
{
|
||||
return pNextTimer ? EXPIRE_TIME( pNextTimer, GetTickCount() ) : -1;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* TIMER_CheckTimer
|
||||
* TIMER_ExpireTimers
|
||||
*
|
||||
* Check whether a timer has expired, and create a message if necessary.
|
||||
* Otherwise, return time until next timer expiration in 'next'.
|
||||
* If 'hwnd' is not NULL, only consider timers for this window.
|
||||
* If 'remove' is TRUE, remove all expired timers up to the returned one.
|
||||
* Mark expired timers and wake the appropriate queues.
|
||||
*/
|
||||
BOOL TIMER_CheckTimer( LONG *next, MSG16 *msg, HWND hwnd, BOOL remove )
|
||||
void TIMER_ExpireTimers(void)
|
||||
{
|
||||
TIMER * pTimer = pNextTimer;
|
||||
TIMER *pTimer = pNextTimer;
|
||||
DWORD curTime = GetTickCount();
|
||||
|
||||
while (pTimer && !pTimer->expires) /* Skip already expired timers */
|
||||
pTimer = pTimer->next;
|
||||
while (pTimer && (pTimer->expires <= curTime))
|
||||
{
|
||||
pTimer->expires = 0;
|
||||
QUEUE_IncTimerCount( pTimer->hq );
|
||||
pTimer = pTimer->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* TIMER_GetTimerMsg
|
||||
*
|
||||
* Build a message for an expired timer.
|
||||
*/
|
||||
BOOL TIMER_GetTimerMsg( MSG16 *msg, HWND hwnd, HQUEUE hQueue, BOOL remove )
|
||||
{
|
||||
TIMER *pTimer = pNextTimer;
|
||||
DWORD curTime = GetTickCount();
|
||||
|
||||
if (hwnd) /* Find first timer for this window */
|
||||
while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next;
|
||||
else /* Find first timer for this queue */
|
||||
while (pTimer && (pTimer->hq != hQueue)) pTimer = pTimer->next;
|
||||
|
||||
if (!pTimer) *next = -1;
|
||||
else *next = EXPIRE_TIME( pTimer, curTime );
|
||||
if (*next != 0) return FALSE; /* No timer expired */
|
||||
if (!pTimer || (pTimer->expires > curTime)) return FALSE; /* No timer */
|
||||
if (remove) TIMER_RestartTimer( pTimer, curTime ); /* Restart it */
|
||||
|
||||
if (remove) /* Restart all timers before pTimer, and then pTimer itself */
|
||||
{
|
||||
while (pNextTimer != pTimer) TIMER_RestartTimer( pNextTimer, curTime );
|
||||
TIMER_RestartTimer( pTimer, curTime );
|
||||
}
|
||||
dprintf_timer( stddeb, "Timer expired: %04x, %04x, %04x, %08lx\n",
|
||||
pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
|
||||
|
||||
dprintf_timer(stddeb, "Timer expired: %p, %04x, %04x, %04x, %08lx\n",
|
||||
pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
|
||||
/* Build the message */
|
||||
msg->hwnd = pTimer->hwnd;
|
||||
msg->message = pTimer->msg;
|
||||
|
@ -218,10 +232,10 @@ static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
|
|||
(pTimer->timeout != 0))
|
||||
{
|
||||
/* Got one: set new values and return */
|
||||
pTimer->timeout = timeout;
|
||||
pTimer->expires = GetTickCount() + timeout;
|
||||
pTimer->proc = proc;
|
||||
TIMER_RemoveTimer( pTimer );
|
||||
pTimer->timeout = timeout;
|
||||
pTimer->proc = proc;
|
||||
pTimer->expires = GetTickCount() + timeout;
|
||||
TIMER_InsertTimer( pTimer );
|
||||
return id;
|
||||
}
|
||||
|
@ -248,7 +262,6 @@ static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
|
|||
dprintf_timer(stddeb, "Timer added: %p, %04x, %04x, %04x, %08lx\n",
|
||||
pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
|
||||
TIMER_InsertTimer( pTimer );
|
||||
QUEUE_IncTimerCount( pTimer->hq );
|
||||
if (!id)
|
||||
return TRUE;
|
||||
else
|
||||
|
|
|
@ -347,7 +347,7 @@ static void WIN_DestroyWindow( HWND hwnd )
|
|||
if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
|
||||
if (wndPtr->window) XDestroyWindow( display, wndPtr->window );
|
||||
if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->hdce );
|
||||
WIN_SetWndProc( wndPtr, (WNDPROC16)0, WIN_PROC_16 );
|
||||
WIN_SetWndProc( wndPtr, (HANDLE32)0, WIN_PROC_16 );
|
||||
wndPtr->class->cWindows--;
|
||||
USER_HEAP_FREE( hwnd );
|
||||
}
|
||||
|
@ -426,7 +426,7 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
pWndDesktop->hProp = 0;
|
||||
pWndDesktop->userdata = 0;
|
||||
|
||||
EVENT_RegisterWindow( pWndDesktop->window, hwndDesktop );
|
||||
EVENT_RegisterWindow( pWndDesktop );
|
||||
SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 );
|
||||
if ((hdc = GetDC( hwndDesktop )) != 0)
|
||||
{
|
||||
|
@ -628,7 +628,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom,
|
|||
Window win = WIN_GetXWindow( cs->hwndParent );
|
||||
if (win) XSetTransientForHint( display, wndPtr->window, win );
|
||||
}
|
||||
EVENT_RegisterWindow( wndPtr->window, hwnd );
|
||||
EVENT_RegisterWindow( wndPtr );
|
||||
}
|
||||
|
||||
/* Set the window menu */
|
||||
|
|
Loading…
Reference in New Issue