Release 960331
Sun Mar 31 13:54:46 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [tools/build.c]
Changed BuildSpec32Files() to generate assembly instead of C code.
Unified -spec16 and -spec32 options; DLL type is now determined by
the 'type' declaration in the .spec file.
New -stdcall option to build all stdcall assembly relays.
* [if1632/relay.c] [if1632/relay32.c] [include/dlls.h]
Started to unify 16- and 32-bit builtin DLLs.
* [loader/module.c]
Added MODULE_GetWndProcEntry32() to mirror MODULE_GetWndProcEntry16().
* [loader/pe_image.c] [loader/resource.c]
All modules now have a NE signature, and can be distinguished by
the NE_FFLAGS_WIN32 flag.
* [windows/alias.c]
Aliases for built-in window procedures are now all created at
startup in ALIAS_Init().
Fri Mar 29 14:56:39 1996 Greg Kreider <kreider@natlab.research.philips.com>
* [controls/combo.c]
Limit rectangle to clear to size of item when painting combo, not
default. Only draw items in list when there is enough room for them.
* [controls/listbox.c]
Get the measure of every item that's added and store in the item's
data structure. Scroll listbox if mouse near edge of box. Only
draw items in list when there is enough room.
Fri Mar 29 12:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [windows/defwnd.c] [windows/dialog.c] [windows/mdi.c]
[windows/nonclient.c] [controls/menu.c]
Various changes for better keyboard handling.
* [windows/event.c] [windows/message.c] [misc/keyboard.c]
Proper keyboard message ordering, working GetKeyState() (finally!),
improvements in ToAscii().
* [windows/win.c] [windows/message.c]
Small improvements in WIN_FindWinToRepaint.
* [windows/win.c] [windows/painting.c] [windows/nonclient.c]
Put update region in WM_NCPAINT wParam.
* [loader/task.c]
Kill task timers when task is deleted, switch timers to the
new queue in SetTaskQueue().
* [loader/signal.c] [miscemu/dosmem.c]
Added SIGALRM signal handler to increment BIOS clock.
* [windows/win.c] [windows/winpos.c] [windows/mdi.c]
Fixed ChildWindowFromPoint(), WM_PARENTNOTIFY and its handling by
MDI client.
* [windows/winpos.c]
Improvements in handling of owned popups. "Floating" toolboxes
work better now.
Thu Mar 28 12:38:29 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [misc/registry.c]
New file, registry rewrite including win32 extensions
- Unicode
- multiple valus per key
- different datatypes for values
- multiple rootkeys
- saving and loading in different registries.
* [include/winreg.h]
New file, definitions and structs for registry.
* [include/winerror.h]
Some new error defines added... there are more, someone please
check a (real-)windows winerror.h.
* [if1632/shell.spec] [if1632/advapi32.spec] [if1632/kernel.spec]
Registry specs added.
* [if1632/relay.c]
Switch internal SHELL.DLL to default 'used'.
* [win32/string32.c] [include/string32.h]
Some new functions added.
char should be unsigned char when converting to 16bit ints.
* [misc/shell.c] [include/shell.h] [win32/advapi.c]
Removed old registry functions.
Tue Mar 26 15:01:46 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>
* [include/bitmaps/ocr_ibeam]
Fixed the position of the hotspot.
* [objects/text.c]
Fixed a few bugs in TEXT_TabbedTextOut().
* [windows/event.c]
Fixed the order of the bits in the KeyStateTable.
0x80 is the up/down-bit. 0x01 is the toggle bit.
* [loader/resource.c] [windows/mdi.c] [controls/edit.c]
Fixed the calls to GetKeyState().
Tue Mar 26 08:43:15 1996 Robert Pouliot <krynos@qbc.clic.net>
* [resources/sysres_Fr.rc] [resources/TODO]
Updated FIND_TEXT and REPLACE_TEXT to work like the English version.
Mon Mar 25 17:38:59 1996 Tristan Tarrant <tst@dcs.ed.ac.uk>
* [resources/sysres_it.rc]
Added support for Italian [It] language.
diff --git a/windows/alias.c b/windows/alias.c
index df87319..5716094 100644
--- a/windows/alias.c
+++ b/windows/alias.c
@@ -7,6 +7,7 @@
#include "windows.h"
#include "alias.h"
+#include "module.h"
#include "stddebug.h"
#include "debug.h"
@@ -22,6 +23,22 @@
int ALIAS_UseAliases;
+/* Aliased window procedures */
+extern LRESULT ButtonWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT StaticWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ScrollBarWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ListBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ComboBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT ComboLBoxWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT EditWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT PopupMenuWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT DesktopWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT DefDlgProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT MDIClientWndProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT AboutDlgProc( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT CARET_Callback( HWND, UINT, WPARAM, LPARAM );
+extern LRESULT SystemMessageBoxProc( HWND, UINT, WPARAM, LPARAM );
+
/* closed hashing */
static int ALIAS_LocateHash(DWORD value)
{
@@ -41,6 +58,48 @@
return hash;
}
+
+/***********************************************************************
+ * ALIAS_RegisterWndProcAlias
+ */
+static void ALIAS_RegisterWndProcAlias( DWORD Wine, const char *name )
+{
+ FARPROC Win16Proc, Win32Proc;
+
+ Win16Proc = MODULE_GetWndProcEntry16( name );
+ Win32Proc = MODULE_GetWndProcEntry32( name );
+ ALIAS_RegisterAlias( Wine, (DWORD)Win16Proc, (DWORD)Win32Proc );
+}
+
+
+/***********************************************************************
+ * ALIAS_Init
+ *
+ * Create aliases for the standard window procedures.
+ */
+BOOL ALIAS_Init(void)
+{
+ ALIAS_RegisterWndProcAlias( (DWORD)ButtonWndProc, "ButtonWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)StaticWndProc, "StaticWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)ScrollBarWndProc, "ScrollBarWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)ListBoxWndProc, "ListBoxWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)ComboBoxWndProc, "ComboBoxWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)ComboLBoxWndProc, "ComboLBoxWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)EditWndProc, "EditWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)PopupMenuWndProc, "PopupMenuWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)DesktopWndProc, "DesktopWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)DefDlgProc, "DefDlgProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)MDIClientWndProc, "MDIClientWndProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)AboutDlgProc, "AboutDlgProc" );
+ ALIAS_RegisterWndProcAlias( (DWORD)CARET_Callback, "CARET_Callback" );
+ ALIAS_RegisterWndProcAlias( (DWORD)SystemMessageBoxProc, "SystemMessageBoxProc" );
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * ALIAS_RegisterAlias
+ */
void ALIAS_RegisterAlias(DWORD Wine,DWORD Win16, DWORD Win32)
{
int whash = 0, w16hash = 0, w32hash = 0, recno=0;
diff --git a/windows/caret.c b/windows/caret.c
index b753d86..294fac5 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -6,9 +6,7 @@
*/
#include "windows.h"
-#include "selectors.h"
-#include "alias.h"
-#include "relay32.h"
+#include "module.h"
#include "stddebug.h"
/* #define DEBUG_CARET */
#include "debug.h"
@@ -88,7 +86,7 @@
{
if (Caret.timerid) KillSystemTimer((HWND)0, Caret.timerid);
Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout,
- (FARPROC)GetWndProcEntry16("CARET_Callback"));
+ MODULE_GetWndProcEntry16("CARET_Callback"));
}
@@ -101,7 +99,7 @@
{
KillSystemTimer((HWND)0, Caret.timerid);
Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout,
- (FARPROC)GetWndProcEntry16("CARET_Callback"));
+ MODULE_GetWndProcEntry16("CARET_Callback"));
}
}
@@ -120,27 +118,6 @@
/*****************************************************************
- * CARET_Initialize
- */
-static void CARET_Initialize()
-{
- DWORD WineProc,Win16Proc,Win32Proc;
- static int initialized=0;
-
- if(!initialized)
- {
- WineProc = (DWORD)CARET_Callback;
- Win16Proc = (DWORD)GetWndProcEntry16("CARET_Callback");
- Win32Proc = (DWORD)RELAY32_GetEntryPoint(
- RELAY32_GetBuiltinDLL("WINPROCS32"),
- "CARET_Callback", 0);
- ALIAS_RegisterAlias(WineProc, Win16Proc, Win32Proc);
- initialized=1;
- }
-}
-
-
-/*****************************************************************
* CreateCaret (USER.163)
*/
BOOL CreateCaret(HWND hwnd, HBITMAP bitmap, INT width, INT height)
@@ -176,9 +153,6 @@
Caret.y = 0;
Caret.timeout = GetProfileInt( "windows", "CursorBlinkRate", 750 );
-
- CARET_Initialize();
-
return TRUE;
}
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 530c5e5..d081f22 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -21,7 +21,11 @@
/* Last COLOR id */
#define COLOR_MAX COLOR_BTNHIGHLIGHT
-static short iMenuKey = 0;
+ /* bits in the dwKeyData */
+#define KEYDATA_ALT 0x2000
+#define KEYDATA_PREVSTATE 0x4000
+
+static short iF10Key = 0;
static short iMenuSysKey = 0;
/***********************************************************************
@@ -73,7 +77,7 @@
case WM_PAINTICON:
case WM_NCPAINT:
- return NC_HandleNCPaint( hwnd );
+ return NC_HandleNCPaint( hwnd, (HRGN)wParam );
case WM_NCHITTEST:
{
@@ -246,7 +250,7 @@
case WM_SETTEXT:
DEFWND_SetText( hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam) );
- NC_HandleNCPaint( hwnd ); /* Repaint caption */
+ NC_HandleNCPaint( hwnd , (HRGN)1 ); /* Repaint caption */
return 0;
case WM_SETCURSOR:
@@ -257,47 +261,77 @@
return NC_HandleSetCursor( hwnd, wParam, lParam );
case WM_SYSCOMMAND:
- {
- POINT pt = { LOWORD(lParam), HIWORD(lParam) };
- return NC_HandleSysCommand( hwnd, wParam, pt );
- }
-
+ {
+ POINT pt = { LOWORD(lParam), HIWORD(lParam) };
+ return NC_HandleSysCommand( hwnd, wParam, pt );
+ }
case WM_KEYDOWN:
- if(wParam == VK_F10) iMenuKey = VK_F10;
+ if(wParam == VK_F10) iF10Key = VK_F10;
break;
case WM_SYSKEYDOWN:
- /* this breaks current pseudo accelerators but
- creates a basis for implementing real ones */
- if(wParam == VK_F10)
- {
- iMenuKey = VK_F10;
- break;
- }
-
- if (wParam == VK_MENU)
- {
- iMenuSysKey = (iMenuSysKey)? 0: 1;
- iMenuKey = 0;
- }
+ if( HIWORD(lParam) & KEYDATA_ALT )
+ {
+ /* if( HIWORD(lParam) & ~KEYDATA_PREVSTATE ) */
+ if( wParam == VK_MENU && !iMenuSysKey )
+ iMenuSysKey = 1;
+ else
+ iMenuSysKey = 0;
+
+ iF10Key = 0;
+
+ }
+ else if( wParam == VK_F10 )
+ iF10Key = 1;
+ else
+ if( wParam == VK_ESCAPE && GetKeyState(VK_SHIFT) < 0 )
+ SendMessage( hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU,
+ (LPARAM)VK_SPACE);
break;
case WM_KEYUP:
case WM_SYSKEYUP:
- if( (wParam == VK_MENU && iMenuSysKey) ||
- (wParam == VK_F10 && iMenuKey) )
+ /* Press and release F10 or ALT */
- /* Send to WS_OVERLAPPED parent. TODO: Handle MDI */
+ if( ( wParam == VK_MENU && iMenuSysKey )
+ || ( wParam == VK_F10 && iF10Key ) )
+
SendMessage( WIN_GetTopParent(hwnd), WM_SYSCOMMAND,
SC_KEYMENU, 0L );
- iMenuSysKey = 0;
- iMenuKey = 0;
+ iMenuSysKey = iF10Key = 0;
break;
+ case WM_SYSCHAR:
+
+ iMenuSysKey = 0;
+
+ if( wParam == VK_RETURN && (wndPtr->dwStyle & WS_MINIMIZE) )
+ {
+ PostMessage(hwnd, WM_SYSCOMMAND, (WPARAM)SC_RESTORE, 0L );
+ break;
+ }
+
+ if( (HIWORD(lParam) & KEYDATA_ALT) && wParam )
+ {
+ if( wParam == VK_TAB || wParam == VK_ESCAPE )
+ break;
+
+ if( wParam == VK_SPACE && (wndPtr->dwStyle & WS_CHILD) )
+ SendMessage( wndPtr->parent->hwndSelf, msg, wParam, lParam );
+ else
+ SendMessage(hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (LPARAM)(DWORD)wParam );
+ }
+ else
+ /* check for Ctrl-Esc */
+ if( wParam != VK_ESCAPE )
+ MessageBeep(0);
+
+ break;
+
case WM_SHOWWINDOW:
if( !lParam ) return 0; /* sent from ShowWindow */
diff --git a/windows/dialog.c b/windows/dialog.c
index 793cffb..a3fc33d 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -655,6 +655,9 @@
#endif
}
break;
+
+ default:
+ TranslateMessage( msg );
}
break; /* case WM_KEYDOWN */
diff --git a/windows/event.c b/windows/event.c
index eba633f..19fa10a 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -54,8 +54,12 @@
BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
BYTE KeyStateTable[256];
BYTE AsyncKeyStateTable[256];
-static WORD ALTKeyState;
-static HWND captureWnd = 0;
+
+
+ WPARAM lastEventChar = 0; /* this will have to be changed once
+ * ToAscii starts working */
+
+static HWND captureWnd = 0;
static BOOL InputEnabled = TRUE;
/* Keyboard translation tables */
@@ -114,7 +118,8 @@
unsigned long count : 16;
unsigned long code : 8;
unsigned long extended : 1;
- unsigned long : 4;
+ unsigned long : 2;
+ unsigned long reserved : 2;
unsigned long context : 1;
unsigned long previous : 1;
unsigned long transition : 1;
@@ -303,10 +308,11 @@
KEYLP keylp;
BOOL extended = FALSE;
- int count = XLookupString(event, Str, 1, &keysym, &cs);
- Str[count] = '\0';
- dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
- keysym, count, Str[0], Str);
+ int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
+
+ Str[ascii_chars] = '\0';
+ dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n",
+ keysym, ascii_chars, Str[0], Str);
/* Ctrl-Alt-Return enters the debugger */
if ((keysym == XK_Return) && (event->type == KeyPress) &&
@@ -343,60 +349,59 @@
}
else if (key_type == 0) /* character key */
{
- if (isalnum(key))
- vkey = toupper(key); /* convert lower to uppercase */
- else
- vkey = 0xbe;
+ if ( isalnum(key) )
+ vkey = toupper(key); /* convert lower to uppercase */
+ else
+ vkey = 0xbe;
}
if (event->type == KeyPress)
{
- if (vkey == VK_MENU) ALTKeyState = TRUE;
- if (!(KeyStateTable[vkey] & 0x0f))
- KeyStateTable[vkey] ^= 0x80;
- KeyStateTable[vkey] |= 0x01;
+ if (!(KeyStateTable[vkey] & 0x80))
+ KeyStateTable[vkey] ^= 0x01;
+ KeyStateTable[vkey] |= 0x80;
keylp.lp1.count = 1;
keylp.lp1.code = LOBYTE(event->keycode) - 8;
keylp.lp1.extended = (extended ? 1 : 0);
- keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+ keylp.lp1.reserved = (ascii_chars ? 1 : 0);
+ keylp.lp1.context = ( (event->state & Mod1Mask) ||
+ (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
keylp.lp1.previous = (KeyDown ? 0 : 1);
keylp.lp1.transition = 0;
dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
vkey, keylp.lp2 );
dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
- hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN,
+ hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN,
vkey, keylp.lp2,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
KeyDown = TRUE;
- /* The key translation ought to take place in TranslateMessage().
- * However, there is no way of passing the required information
- * in a Windows message, so TranslateMessage does not currently
- * do anything and the translation is done here.
+ /* Currently we use reserved field in the scan-code byte to
+ * make it possible for TranslateMessage to recognize character keys
+ * and get them from lastEventChar global variable.
+ *
+ * ToAscii should handle it.
*/
- if (count == 1) /* key has an ASCII representation */
- {
- dprintf_key(stddeb,"WM_CHAR : wParam=%X\n", (WORD)Str[0] );
- PostMessage( GetFocus(), WM_CHAR, (WORD)(unsigned char)(Str[0]),
- keylp.lp2 );
- }
+
+ if( ascii_chars ) lastEventChar = Str[0];
}
else
{
- if (vkey == VK_MENU) ALTKeyState = FALSE;
- KeyStateTable[vkey] &= 0xf0;
+ UINT sysKey = KeyStateTable[VK_MENU];
+
+ KeyStateTable[vkey] &= ~0x80;
keylp.lp1.count = 1;
keylp.lp1.code = LOBYTE(event->keycode) - 8;
keylp.lp1.extended = (extended ? 1 : 0);
+ keylp.lp1.reserved = 0;
keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
keylp.lp1.previous = 1;
keylp.lp1.transition = 1;
dprintf_key(stddeb," wParam=%X, lParam=%lX\n",
vkey, keylp.lp2 );
dprintf_key(stddeb," KeyState=%X\n", KeyStateTable[vkey]);
- hardware_event( ((ALTKeyState || vkey == VK_MENU) ?
- WM_SYSKEYUP : WM_KEYUP),
+ hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP,
vkey, keylp.lp2,
event->x_root - desktopX, event->y_root - desktopY,
event->time, 0 );
diff --git a/windows/keyboard.c b/windows/keyboard.c
index 0c1ae3e..bdf8030 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -15,8 +15,10 @@
/**********************************************************************
* GetKeyState [USER.106]
*/
-int GetKeyState(int keycode)
+INT GetKeyState(INT keycode)
{
+ INT retval;
+
switch(keycode) {
case VK_LBUTTON:
return MouseButtonsStates[0];
@@ -25,8 +27,11 @@
case VK_RBUTTON:
return MouseButtonsStates[2];
default:
- return KeyStateTable[keycode];
+ retval = ( (INT)(KeyStateTable[keycode] & 0x80) << 8 ) |
+ (INT)(KeyStateTable[keycode] & 0x01);
}
+
+ return retval;
}
/**********************************************************************
diff --git a/windows/mdi.c b/windows/mdi.c
index f3f8000..a22d1de 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -174,7 +174,10 @@
if (!wTo || !pWndLast) return 0;
break;
}
- if ((pWnd->dwStyle & WS_VISIBLE) &&
+
+ /* we are not interested in owned popups */
+ if ( !pWnd->owner &&
+ (pWnd->dwStyle & WS_VISIBLE) &&
!(pWnd->dwStyle & WS_DISABLED)) /* found one */
{
pWndLast = pWnd;
@@ -782,7 +785,7 @@
hSysPopup = GetSystemMenu(hChild,FALSE);
- dprintf_mdi(stddeb,"got popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
+ dprintf_mdi(stddeb,"\t\tgot popup %04x\n in sysmenu %04x",hSysPopup,child->hSysMenu);
if( !InsertMenu(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
hSysPopup, (SEGPTR)(DWORD)ci->obmClose) )
@@ -795,6 +798,10 @@
return 0;
}
+ /* FIXME: add a call to function that sets sysmenu items according
+ * to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
+ */
+
EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
@@ -823,6 +830,10 @@
child->dwStyle |= WS_SYSMENU;
+ /* FIXME: add a call to function that sets sysmenu items according
+ * to the window state. WS_MAXIMIZE -> no SC_SIZE, etc...
+ */
+
RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
@@ -1057,9 +1068,25 @@
break;
case WM_PARENTNOTIFY:
- if (wParam == WM_LBUTTONDOWN && (ci->hwndHitTest != ci->hwndActiveChild) )
- SetWindowPos(ci->hwndHitTest, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
- break;
+ if( wParam == WM_LBUTTONDOWN )
+ {
+ LPPOINT lppt = (LPPOINT)(void*)(&lParam);
+ HWND child = ChildWindowFromPoint(hwnd, *lppt);
+
+ dprintf_mdi(stddeb,"MDIClient: notification from %04x (%i,%i)\n",child,lppt->x,lppt->y);
+
+ if( child && child != hwnd )
+ {
+ WND* wnd = WIN_FindWndPtr( child );
+
+ /* if we got owned popup */
+ if( wnd->owner ) child = wnd->owner->hwndSelf;
+
+ if( child != ci->hwndActiveChild )
+ SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE );
+ }
+ }
+ return 0;
case WM_SIZE:
if( ci->flagChildMaximized )
@@ -1178,10 +1205,6 @@
switch (message)
{
- case WM_NCHITTEST:
- ci->hwndHitTest = hwnd;
- break;
-
case WM_SETTEXT:
DefWindowProc(hwnd, message, wParam, lParam);
MDI_MenuModifyItem(clientWnd,hwnd);
@@ -1291,6 +1314,12 @@
break;
case WM_MENUCHAR:
+
+ /* MDI children don't have menus */
+ PostMessage( clientWnd->parent->hwndSelf, WM_SYSCOMMAND,
+ (WPARAM)SC_KEYMENU, (LPARAM)wParam);
+ return 0x00010000L;
+
case WM_NEXTMENU:
/* set current menu to child system menu */
@@ -1321,18 +1350,21 @@
if( wnd->dwStyle & WS_DISABLED ) return 0;
- if( GetKeyState(VK_CONTROL) && !GetKeyState(VK_MENU) )
+ if ((GetKeyState(VK_CONTROL) & 0x8000) && !(GetKeyState(VK_MENU) & 0x8000))
switch( msg->wParam )
{
case VK_F6:
case VK_SEPARATOR:
- wParam = (GetKeyState(VK_SHIFT))? SC_NEXTWINDOW: SC_PREVWINDOW;
+ wParam = ( GetKeyState(VK_SHIFT) & 0x8000 )? SC_NEXTWINDOW: SC_PREVWINDOW;
break;
case VK_RBUTTON:
wParam = SC_CLOSE;
+ break;
default:
return 0;
}
+ else
+ return 0;
dprintf_mdi(stddeb,"TranslateMDISysAccel: wParam = %04x\n", wParam);
diff --git a/windows/message.c b/windows/message.c
index 415f39c..6a88fc6 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -26,10 +26,13 @@
#define HWND_BROADCAST ((HWND)0xffff)
+extern BYTE* KeyStateTable; /* event.c */
+extern WPARAM lastEventChar; /* event.c */
+
extern BOOL TIMER_CheckTimer( LONG *next, MSG *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;
@@ -180,8 +183,11 @@
{
/* Send the message to the active window instead, */
/* translating messages to their WM_SYS equivalent */
+
msg->hwnd = GetActiveWindow();
- msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
+
+ if( msg->message < WM_SYSKEYDOWN )
+ msg->message += WM_SYSKEYDOWN - WM_KEYDOWN;
}
return !HOOK_CallHooks( WH_KEYBOARD, remove ? HC_ACTION : HC_NOREMOVE,
msg->wParam, msg->lParam );
@@ -383,6 +389,7 @@
{
int pos, mask;
MESSAGEQUEUE *msgQueue;
+ HQUEUE hQueue;
LONG nextExp; /* Next timer expiration time */
#ifdef CONFIG_IPC
@@ -403,7 +410,8 @@
while(1)
{
- msgQueue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) );
+ hQueue = GetTaskQueue(0);
+ msgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
if (!msgQueue) return FALSE;
/* First handle a message put by SendMessage() */
@@ -461,11 +469,24 @@
/* Now find a WM_PAINT message */
if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
{
- msg->hwnd = WIN_FindWinToRepaint( hwnd );
+ msg->hwnd = WIN_FindWinToRepaint( hwnd , hQueue );
msg->message = WM_PAINT;
msg->wParam = 0;
msg->lParam = 0;
- if (msg->hwnd != 0) break;
+ if( msg->hwnd &&
+ (!hwnd || msg->hwnd == hwnd || IsChild(hwnd,msg->hwnd)) )
+ {
+ WND* wndPtr = WIN_FindWndPtr(msg->hwnd);
+
+ /* FIXME: WM_PAINTICON should be sent sometimes */
+
+ if( wndPtr->flags & WIN_INTERNAL_PAINT && !wndPtr->hrgnUpdate)
+ {
+ wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+ QUEUE_DecPaintCount( hQueue );
+ }
+ break;
+ }
}
/* Finally handle WM_TIMER messages */
@@ -547,10 +568,14 @@
*/
BOOL GetMessage( SEGPTR msg, HWND hwnd, UINT first, UINT last )
{
- MSG_PeekMessage( (MSG *)PTR_SEG_TO_LIN(msg),
+ MSG* lpmsg = (MSG *)PTR_SEG_TO_LIN(msg);
+ MSG_PeekMessage( lpmsg,
hwnd, first, last, PM_REMOVE, FALSE );
+
+ dprintf_msg(stddeb,"message %04x, hwnd %04x, filter(%04x - %04x)\n", lpmsg->message,
+ hwnd, first, last );
HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, 0, (LPARAM)msg );
- return (((MSG *)PTR_SEG_TO_LIN(msg))->message != WM_QUIT);
+ return (lpmsg->message != WM_QUIT);
}
@@ -697,16 +722,35 @@
/***********************************************************************
* TranslateMessage (USER.113)
+ *
+ * This should call ToAscii but it is currently broken
*/
+
+#define ASCII_CHAR_HACK 0x0800
+
BOOL TranslateMessage( LPMSG msg )
{
- int message = msg->message;
+ UINT message = msg->message;
+ /* BYTE wparam[2]; */
if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
(message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
{
- dprintf_msg(stddeb, "Translating key message\n" );
- return TRUE;
+ dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam,
+ HIWORD(msg->lParam) );
+
+ if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
+
+ /* if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
+ wparam, 0 ) )
+ */
+ {
+ message += 2 - (message & 0x0001);
+
+ PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
+
+ return TRUE;
+ }
}
return FALSE;
}
diff --git a/windows/msgbox.c b/windows/msgbox.c
index 33ebe2c..c8215fd 100644
--- a/windows/msgbox.c
+++ b/windows/msgbox.c
@@ -7,9 +7,7 @@
#include "windows.h"
#include "dlgs.h"
-#include "selectors.h"
-#include "alias.h"
-#include "relay32.h"
+#include "module.h"
#include "win.h"
#include "resource.h"
#include "task.h"
@@ -185,27 +183,16 @@
MSGBOX mbox;
int ret;
DWORD WineProc,Win16Proc,Win32Proc;
- static int initialized = 0;
mbox.title = title;
mbox.text = text;
mbox.type = type;
- if (!initialized)
- {
- WineProc=(DWORD)SystemMessageBoxProc;
- Win16Proc=(DWORD)GetWndProcEntry16("SystemMessageBoxProc");
- Win32Proc=(DWORD)RELAY32_GetEntryPoint(RELAY32_GetBuiltinDLL("WINPROCS32"),
- "SystemMessageBoxProc",0);
- ALIAS_RegisterAlias(WineProc,Win16Proc,Win32Proc);
- initialized=1;
- }
-
handle = SYSRES_LoadResource( SYSRES_DIALOG_MSGBOX );
if (!handle) return 0;
ret = DialogBoxIndirectParam( WIN_GetWindowInstance(hWnd),
handle, hWnd,
- GetWndProcEntry16("SystemMessageBoxProc"),
+ MODULE_GetWndProcEntry16("SystemMessageBoxProc"),
(LONG)&mbox );
SYSRES_FreeResource( handle );
return ret;
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 70b8125..c94ca9c 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -18,6 +18,7 @@
#include "scroll.h"
#include "nonclient.h"
#include "graphics.h"
+#include "queue.h"
#include "selectors.h"
#include "stackframe.h"
#include "stddebug.h"
@@ -618,18 +619,22 @@
/***********************************************************************
* NC_DoNCPaint
*
- * Paint the non-client area.
+ * Paint the non-client area. clip is currently unused.
*/
-void NC_DoNCPaint( HWND hwnd, BOOL active, BOOL suppress_menupaint )
+void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
{
- HDC hdc;
- RECT rect;
+ HDC hdc;
+ RECT rect;
+ BOOL active;
WND *wndPtr = WIN_FindWndPtr( hwnd );
- dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
if (!wndPtr || !(wndPtr->dwStyle & WS_VISIBLE)) return; /* Nothing to do */
+ active = wndPtr->flags & WIN_NCACTIVATED;
+
+ dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
+
if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
/*
@@ -646,6 +651,13 @@
DrawIcon(hdc, 0, 0, hIcon);
}
ReleaseDC(hwnd, hdc);
+ wndPtr->flags &= ~WIN_INTERNAL_PAINT;
+ if( wndPtr->hrgnUpdate )
+ {
+ DeleteObject( wndPtr->hrgnUpdate );
+ QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
+ wndPtr->hrgnUpdate = 0;
+ }
return;
}
@@ -724,11 +736,9 @@
*
* Handle a WM_NCPAINT message. Called from DefWindowProc().
*/
-LONG NC_HandleNCPaint( HWND hwnd )
+LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
{
- WND *wndPtr = WIN_FindWndPtr(hwnd);
-
- NC_DoNCPaint( hwnd, wndPtr->flags & WIN_NCACTIVATED, FALSE );
+ NC_DoNCPaint( hwnd, clip, FALSE );
return 0;
}
@@ -745,7 +755,7 @@
if (wParam != 0) wndPtr->flags |= WIN_NCACTIVATED;
else wndPtr->flags &= ~WIN_NCACTIVATED;
- NC_DoNCPaint( hwnd, (wParam != 0), FALSE );
+ NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
return TRUE;
}
@@ -1297,7 +1307,7 @@
dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n",
wParam, pt.x, pt.y );
- if (wndPtr->dwStyle & WS_CHILD)
+ if (wndPtr->dwStyle & WS_CHILD && wParam != SC_KEYMENU )
ScreenToClient( wndPtr->parent->hwndSelf, &pt );
switch (wParam & 0xfff0)
@@ -1336,7 +1346,7 @@
break;
case SC_KEYMENU:
- MENU_TrackKbdMenuBar( hwnd, wParam );
+ MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
break;
case SC_ARRANGE:
diff --git a/windows/painting.c b/windows/painting.c
index bd1554c..e8ce1bb 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -17,6 +17,64 @@
/* Last CTLCOLOR id */
#define CTLCOLOR_MAX CTLCOLOR_STATIC
+/***********************************************************************
+ * WIN_UpdateNCArea
+ *
+ */
+void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
+{
+ RECT rect = wnd->rectClient;
+ HRGN hClip = 1;
+
+ dprintf_nonclient(stddeb,"NCUpdate: hwnd %04x, hrgnUpdate %04x\n",
+ wnd->hwndSelf, wnd->hrgnUpdate );
+
+ /* desktop windows doesn't have nonclient area */
+ if(wnd == WIN_GetDesktop())
+ {
+ wnd->flags &= ~WIN_NEEDS_NCPAINT;
+ return;
+ }
+
+ if( wnd->hrgnUpdate > 1 )
+ {
+ MapWindowPoints(wnd->parent->hwndSelf, 0, (POINT*)&rect, 2);
+
+ hClip = CreateRectRgn( 0, 0, 0, 0 );
+ if (!CombineRgn(hClip, wnd->hrgnUpdate, 0, RGN_COPY) )
+ {
+ DeleteObject(hClip);
+ hClip = 1;
+ }
+
+ if (bUpdate)
+ {
+ HRGN hrgn = CreateRectRgnIndirect(&rect);
+ if (hrgn && (CombineRgn(wnd->hrgnUpdate, wnd->hrgnUpdate,
+ hrgn, RGN_AND) == NULLREGION))
+ {
+ DeleteObject(wnd->hrgnUpdate);
+ wnd->hrgnUpdate = 1;
+ }
+ DeleteObject( hrgn );
+ }
+ }
+
+ wnd->flags &= ~WIN_NEEDS_NCPAINT;
+
+ if ((wnd->hwndSelf == GetActiveWindow()) &&
+ !(wnd->flags & WIN_NCACTIVATED))
+ {
+ wnd->flags |= WIN_NCACTIVATED;
+ if( hClip > 1) DeleteObject(hClip);
+ hClip = 1;
+ }
+
+ if (hClip) SendMessage( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
+
+ if (hClip > 1) DeleteObject( hClip );
+}
+
/***********************************************************************
* BeginPaint (USER.39)
@@ -27,26 +85,22 @@
WND * wndPtr = WIN_FindWndPtr( hwnd );
if (!wndPtr) return 0;
- hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
- if (!hrgnUpdate) /* Create an empty region */
- if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
+ wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
- if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
- QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
+ if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
+
+ if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
+ (wndPtr->flags & WIN_INTERNAL_PAINT))
+ QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
wndPtr->hrgnUpdate = 0;
- wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
+ wndPtr->flags &= ~WIN_INTERNAL_PAINT;
HideCaret( hwnd );
- if (wndPtr->flags & WIN_NEEDS_NCPAINT)
- {
- wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
- SendMessage( hwnd, WM_NCPAINT, 0, 0 );
- }
-
lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_USESTYLE );
- DeleteObject( hrgnUpdate );
+ if(hrgnUpdate > 1) DeleteObject( hrgnUpdate );
+
if (!lps->hdc)
{
fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
@@ -233,10 +287,8 @@
else if (flags & RDW_ERASENOW)
{
if (wndPtr->flags & WIN_NEEDS_NCPAINT)
- {
- wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
- SendMessage( hwnd, WM_NCPAINT, 0, 0 );
- }
+ WIN_UpdateNCArea( wndPtr, FALSE);
+
if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
{
HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
diff --git a/windows/timer.c b/windows/timer.c
index ca1a620..9f8cc4a 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -14,6 +14,7 @@
typedef struct tagTIMER
{
HWND hwnd;
+ HQUEUE hq;
WORD msg; /* WM_TIMER or WM_SYSTIMER */
WORD id;
WORD timeout;
@@ -74,6 +75,58 @@
pTimer->next = NULL;
}
+/***********************************************************************
+ * TIMER_SwitchQueue
+ */
+void TIMER_SwitchQueue(HQUEUE old, HQUEUE new)
+{
+ TIMER* pT = pNextTimer;
+
+ while(pT)
+ {
+ if( pT->hq == old ) pT->hq = new;
+ pT = pT->next;
+ }
+
+}
+
+/***********************************************************************
+ * TIMER_NukeTimers
+ *
+ * Trash all timers that are bound to the hwnd or hq
+ */
+void TIMER_NukeTimers(HWND hwnd, HQUEUE hq)
+{
+ HQUEUE hQToUpdate = ( hwnd ) ? GetTaskQueue( GetWindowTask( hwnd ) )
+ : hq;
+ TIMER* pT = pNextTimer;
+ TIMER* pTnext;
+
+ if( !pT ) return;
+
+ while( (hwnd && pT->hwnd == hwnd) ||
+ (hq && pT->hq == hq) )
+ {
+ QUEUE_DecTimerCount( hQToUpdate );
+ if( !(pT = pNextTimer = pNextTimer->next) )
+ return;
+ }
+
+ /* pT points to the "good" timer */
+
+ while( (pTnext = pT->next) )
+ {
+ while( (hwnd && pTnext->hwnd == hwnd) ||
+ (hq && pTnext->hq == hq) )
+ {
+ QUEUE_DecTimerCount( hQToUpdate );
+ if( !(pT->next = pTnext->next) )
+ return;
+ }
+
+ pT = pT->next;
+ }
+}
/***********************************************************************
* TIMER_RestartTimers
@@ -165,6 +218,8 @@
/* Add the timer */
pTimer->hwnd = hwnd;
+ pTimer->hq = (hwnd) ? GetTaskQueue( GetWindowTask( hwnd ) )
+ : GetTaskQueue( 0 );
pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
pTimer->id = id;
pTimer->timeout = timeout;
@@ -173,7 +228,7 @@
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( GetTaskQueue(0) );
+ QUEUE_IncTimerCount( pTimer->hq );
if (!id)
return TRUE;
else
@@ -188,6 +243,7 @@
{
int i;
TIMER * pTimer;
+ HQUEUE hq;
/* Find the timer */
@@ -201,13 +257,15 @@
/* Delete the timer */
+ hq = pTimer->hq;
+
pTimer->hwnd = 0;
pTimer->msg = 0;
pTimer->id = 0;
pTimer->timeout = 0;
pTimer->proc = 0;
TIMER_RemoveTimer( pTimer );
- QUEUE_DecTimerCount( GetTaskQueue(0) );
+ QUEUE_DecTimerCount( hq );
return TRUE;
}
diff --git a/windows/win.c b/windows/win.c
index 8511a73..5c0b2ab 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -217,30 +217,43 @@
*
* Find a window that needs repaint.
*/
-HWND WIN_FindWinToRepaint( HWND hwnd )
+HWND WIN_FindWinToRepaint( HWND hwnd, HQUEUE hQueue )
{
- WND * wndPtr;
+ HWND hwndRet;
+ WND *pWnd = pWndDesktop;
- /* Note: the desktop window never gets WM_PAINT messages */
- wndPtr = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
- for ( ; wndPtr; wndPtr = wndPtr->next)
+ /* Note: the desktop window never gets WM_PAINT messages */
+ pWnd = hwnd ? WIN_FindWndPtr( hwnd ) : pWndDesktop->child;
+
+ for ( ; pWnd ; pWnd = pWnd->next )
{
- dprintf_win( stddeb, "WIN_FindWinToRepaint: %04x, style %08lx\n",
- wndPtr->hwndSelf, wndPtr->dwStyle );
- if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
+ if (!(pWnd->dwStyle & WS_VISIBLE) || (pWnd->flags & WIN_NO_REDRAW))
+ {
+ dprintf_win( stddeb, "FindWinToRepaint: skipping window %04x\n",
+ pWnd->hwndSelf );
continue;
- if ((wndPtr->dwStyle & WS_MINIMIZE) && (WIN_CLASS_INFO(wndPtr).hIcon))
- continue;
- if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
- return wndPtr->hwndSelf;
- if (wndPtr->child)
- {
- HWND child;
- if ((child = WIN_FindWinToRepaint( wndPtr->child->hwndSelf )))
- return child;
- }
+ }
+ if ((pWnd->hmemTaskQ == hQueue) &&
+ (pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))) break;
+
+ if (pWnd->child )
+ if ((hwndRet = WIN_FindWinToRepaint( pWnd->child->hwndSelf, hQueue )) )
+ return hwndRet;
}
- return 0;
+
+ if (!pWnd) return 0;
+
+ hwndRet = pWnd->hwndSelf;
+
+ /* look among siblings if we got a transparent window */
+ while (pWnd && ((pWnd->dwExStyle & WS_EX_TRANSPARENT) ||
+ !(pWnd->hrgnUpdate || (pWnd->flags & WIN_INTERNAL_PAINT))))
+ {
+ pWnd = pWnd->next;
+ }
+ if (pWnd) hwndRet = pWnd->hwndSelf;
+ dprintf_win(stddeb,"FindWinToRepaint: found %04x\n",hwndRet);
+ return hwndRet;
}
@@ -252,19 +265,35 @@
*/
void WIN_SendParentNotify( HWND hwnd, WORD event, WORD idChild, LONG lValue )
{
- WND *wndPtr = WIN_FindWndPtr( hwnd );
-
- while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
+ LPPOINT lppt = (LPPOINT)(void*)(&lValue);
+ WND *wndPtr = WIN_FindWndPtr( hwnd );
+ BOOL bMouse = ((event <= WM_MOUSELAST) && (event >= WM_MOUSEFIRST));
+
+ /* if lValue contains cursor coordinates they have to be
+ * mapped to the client area of parent window */
+
+ if (bMouse) MapWindowPoints(0, hwnd, lppt, 2);
+#ifndef WINELIB32
+ else lValue = MAKELONG( LOWORD(lValue), idChild );
+#endif
+
+ while (wndPtr)
{
- if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
+ if ((wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ||
+ !(wndPtr->dwStyle & WS_CHILD)) break;
+
+ if (bMouse)
+ {
+ lppt->x += wndPtr->rectClient.left;
+ lppt->y += wndPtr->rectClient.top;
+ }
+
wndPtr = wndPtr->parent;
#ifdef WINELIB32
SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY,
- MAKEWPARAM(event,idChild),
- (LPARAM)lValue );
+ MAKEWPARAM( event, idChild ), lValue );
#else
- SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY, event,
- MAKELPARAM(LOWORD(lValue), idChild) );
+ SendMessage( wndPtr->hwndSelf, WM_PARENTNOTIFY, event, (LPARAM)lValue);
#endif
}
}
@@ -1268,7 +1297,7 @@
pWndChild = wndPtr->child; /* ..side effects after wndenumprc */
if (!CallEnumWindowsProc( wndenumprc, wndPtr->hwndSelf, lParam ))
return 0;
- if (IsWindow(pWndChild->hwndSelf)) /*to prevent too early termination*/
+ if (pWndChild && IsWindow(pWndChild->hwndSelf))
if (!WIN_EnumChildWin(pWndChild, wndenumprc, lParam)) return 0;
wndPtr = pWndNext;
}
diff --git a/windows/winpos.c b/windows/winpos.c
index 29f3d70..524f285 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -6,7 +6,7 @@
*/
#include "sysmetrics.h"
-#include "selectors.h"
+#include "module.h"
#include "user.h"
#include "win.h"
#include "event.h"
@@ -238,7 +238,7 @@
/* Restart the search from the next sibling */
wndPtr = (*ppWnd)->next;
- *ppWnd = wndPtr->parent;
+ *ppWnd = (*ppWnd)->parent;
}
}
@@ -259,22 +259,29 @@
*/
HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
{
+ /* pt is in the client coordinates */
+
+ WND* wnd = WIN_FindWndPtr(hwndParent);
RECT rect;
- HWND hwnd;
-
- GetWindowRect( hwndParent, &rect );
+
+ if( !wnd ) return 0;
+
+ /* get client rect fast */
+ rect.top = rect.left = 0;
+ rect.right = wnd->rectClient.right - wnd->rectClient.left;
+ rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
+
if (!PtInRect( &rect, pt )) return 0;
- hwnd = GetTopWindow( hwndParent );
- while (hwnd)
+
+ wnd = wnd->child;
+ while ( wnd )
{
- GetWindowRect( hwnd, &rect );
- if (PtInRect( &rect, pt )) return hwnd;
- hwnd = GetWindow( hwnd, GW_HWNDNEXT );
+ if (PtInRect( &wnd->rectWindow, pt )) return wnd->hwndSelf;
+ wnd = wnd->next;
}
return hwndParent;
}
-
/*******************************************************************
* MapWindowPoints (USER.258)
*/
@@ -652,10 +659,15 @@
WND *wndPtr = WIN_FindWndPtr(hWnd);
WND *wndTemp = WIN_FindWndPtr(hwndActive);
CBTACTIVATESTRUCT cbtStruct = { fMouse , hwndActive };
- FARPROC enumCallback = (FARPROC)GetWndProcEntry16("ActivateAppProc");
+ FARPROC enumCallback = MODULE_GetWndProcEntry16("ActivateAppProc");
ACTIVATESTRUCT actStruct;
WORD wIconized=0,wRet= 0;
- HANDLE hActiveQ = 0;
+
+ /* FIXME: When proper support for cooperative multitasking is in place
+ * hActiveQ will be global
+ */
+
+ HANDLE hActiveQ = 0;
/* paranoid checks */
if( !hWnd || hWnd == GetDesktopWindow() || hWnd == hwndActive )
@@ -805,16 +817,24 @@
if( !wndPtr ) return FALSE;
- /* minors are not allowed */
+ /* child windows get WM_CHILDACTIVATE message */
if( (wndPtr->dwStyle & WS_CHILD) && !( wndPtr->dwStyle & WS_POPUP))
return SendMessage(hWnd, WM_CHILDACTIVATE, 0, 0L);
+ /* owned popups imply owner activation */
+ if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
+ {
+ wndPtr = wndPtr->owner;
+ if( !wndPtr ) return FALSE;
+ hWnd = wndPtr->hwndSelf;
+ }
+
if( hWnd == hwndActive ) return FALSE;
if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
return FALSE;
- /* switch desktop queue to current active here */
+ /* switch desktop queue to current active */
if( wndPtr->parent == WIN_GetDesktop())
WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
@@ -947,6 +967,79 @@
}
}
+/***********************************************************************
+ * WINPOS_ReorderOwnedPopups
+ *
+ * fix Z order taking into account owned popups -
+ * basically we need to maintain them above owner window
+ */
+HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter, WND* wndPtr, WORD flags)
+{
+ WND* w = WIN_GetDesktop();
+
+ w = w->child;
+
+ /* if we are dealing with owned popup...
+ */
+ if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner && hwndInsertAfter != HWND_TOP )
+ {
+ BOOL bFound = FALSE;
+ HWND hwndLocalPrev = HWND_TOP;
+ HWND hwndNewAfter = 0;
+
+ while( w )
+ {
+ if( !bFound && hwndInsertAfter == hwndLocalPrev )
+ hwndInsertAfter = HWND_TOP;
+
+ if( w->dwStyle & WS_POPUP && w->owner == wndPtr->owner )
+ {
+ bFound = TRUE;
+
+ if( hwndInsertAfter == HWND_TOP )
+ {
+ hwndInsertAfter = hwndLocalPrev;
+ break;
+ }
+ hwndNewAfter = hwndLocalPrev;
+ }
+
+ if( w == wndPtr->owner )
+ {
+ /* basically HWND_BOTTOM */
+ hwndInsertAfter = hwndLocalPrev;
+
+ if( bFound )
+ hwndInsertAfter = hwndNewAfter;
+ break;
+ }
+
+ if( w != wndPtr )
+ hwndLocalPrev = w->hwndSelf;
+
+ w = w->next;
+ }
+ }
+ else
+ /* or overlapped top-level window...
+ */
+ if( !(wndPtr->dwStyle & WS_CHILD) )
+ while( w )
+ {
+ if( w == wndPtr ) break;
+
+ if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
+ {
+ SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
+ hwndInsertAfter = w->hwndSelf;
+ }
+ w = w->next;
+ }
+
+ return hwndInsertAfter;
+}
+
/***********************************************************************
* WINPOS_SetXWindowPos
@@ -1079,6 +1172,12 @@
if (!(winpos.flags & SWP_NOZORDER))
{
+ /* reorder owned popups if hwnd is top-level window
+ */
+ if( wndPtr->parent == WIN_GetDesktop() )
+ hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
+ wndPtr, flags );
+
if (wndPtr->window)
{
WIN_UnlinkWindow( winpos.hwnd );
@@ -1098,9 +1197,14 @@
if (wndPtr->window)
{
+ HWND bogusInsertAfter = winpos.hwndInsertAfter;
+
+ winpos.hwndInsertAfter = hwndInsertAfter;
WINPOS_SetXWindowPos( &winpos );
+
wndPtr->rectWindow = newWindowRect;
wndPtr->rectClient = newClientRect;
+ winpos.hwndInsertAfter = bogusInsertAfter;
}
else
{