source: trunk/src/user32/pmwindow.cpp@ 2205

Last change on this file since 2205 was 2204, checked in by cbratschi, 26 years ago

non-client fixes, DefWndProc enhancements, several other bugs fixed

File size: 17.4 KB
Line 
1/* $Id: pmwindow.cpp,v 1.70 1999-12-26 17:30:16 cbratschi Exp $ */
2/*
3 * Win32 Window Managment Code for OS/2
4 *
5 * Copyright 1998-1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999 Daniela Engert (dani@ngrt.de)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_WIN
13#define INCL_GPI
14#define INCL_DEV /* Device Function definitions */
15#define INCL_GPICONTROL /* GPI control Functions */
16
17#include <os2wrap.h>
18#include <stdlib.h>
19#include <string.h>
20#include "win32type.h"
21#include <winconst.h>
22#include <wprocess.h>
23#include <misc.h>
24#include <win32wbase.h>
25#include <win32dlg.h>
26#include "win32wdesktop.h"
27#include "pmwindow.h"
28#include "oslibwin.h"
29#include "oslibutil.h"
30#include "oslibgdi.h"
31#include "oslibmsg.h"
32#include "dc.h"
33#include <thread.h>
34#include <wprocess.h>
35#include "caret.h"
36#include "timer.h"
37
38HMQ hmq = 0; /* Message queue handle */
39HAB hab = 0;
40
41RECTL desktopRectl = {0};
42ULONG ScreenWidth = 0;
43ULONG ScreenHeight = 0;
44ULONG ScreenBitsPerPel = 0;
45
46
47MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2);
48
49//******************************************************************************
50//Initialize PM; create hab, message queue and register special Win32 window classes
51//******************************************************************************
52BOOL InitPM()
53{
54 CLASSINFO FrameClassInfo;
55
56 hab = WinInitialize(0);
57 dprintf(("Winitialize returned %x", hab));
58 hmq = WinCreateMsgQueue(hab, 0);
59
60 if(!hab || !hmq)
61 {
62 UINT error;
63 //CB: only fail on real error
64 error = WinGetLastError(hab) & 0xFFFF; //error code
65 if (!hab || error != PMERR_MSG_QUEUE_ALREADY_EXISTS)
66 {
67 dprintf(("WinInitialize or WinCreateMsgQueue failed %x %x", hab, hmq));
68 dprintf((" Error = %x",error));
69 return(FALSE);
70 }
71 else
72 {
73 if(!hab) {
74 hab = WinQueryAnchorBlock(HWND_DESKTOP);
75 dprintf(("WinQueryAnchorBlock returned %x", hab));
76 }
77 if(!hmq) {
78 hmq = HMQ_CURRENT;
79 }
80 }
81 }
82 SetThreadHAB(hab);
83 dprintf(("InitPM: hmq = %x", hmq));
84 SetThreadMessageQueue(hmq);
85
86 if(!WinRegisterClass( /* Register window class */
87 hab, /* Anchor block handle */
88 (PSZ)WIN32_STDCLASS, /* Window class name */
89 (PFNWP)Win32WindowProc, /* Address of window procedure */
90// CS_SIZEREDRAW | CS_HITTEST | CS_MOVENOTIFY,
91 //CS_SIZEREDRAW | CS_HITTEST,
92 CS_HITTEST,
93 NROF_WIN32WNDBYTES)) {
94 dprintf(("WinRegisterClass Win32BaseWindow failed"));
95 return(FALSE);
96 }
97 if (!WinQueryClassInfo (hab, WC_FRAME, &FrameClassInfo)) {
98 dprintf (("WinQueryClassInfo WC_FRAME failed"));
99 return (FALSE);
100 }
101 FrameClassInfo.flClassStyle &= ~(CS_PUBLIC | CS_CLIPSIBLINGS);
102 if (!WinRegisterClass (hab,
103 WIN32_INNERFRAME,
104 FrameClassInfo.pfnWindowProc,
105 FrameClassInfo.flClassStyle,
106 FrameClassInfo.cbWindowData)) {
107 dprintf (("WinRegisterClass Win32InnerFrame failed"));
108 return (FALSE);
109 }
110
111 WinQueryWindowRect(HWND_DESKTOP, &desktopRectl);
112 ScreenWidth = desktopRectl.xRight;
113 ScreenHeight = desktopRectl.yTop;
114
115
116 HDC hdc; /* Device-context handle */
117 /* context data structure */
118 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL,
119 NULL, NULL, NULL};
120
121 /* create memory device context */
122 hdc = DevOpenDC(hab, OD_MEMORY, "*", 5L, (PDEVOPENDATA)&dop, NULLHANDLE);
123 DevQueryCaps(hdc, CAPS_COLOR_BITCOUNT, 1, (PLONG)&ScreenBitsPerPel);
124 DevCloseDC(hdc);
125
126 dprintf(("InitPM: Desktop (%d,%d)", ScreenWidth, ScreenHeight));
127 return OSLibInitMsgQueue();
128} /* End of main */
129//******************************************************************************
130//Win32 window message handler
131//******************************************************************************
132MRESULT EXPENTRY Win32WindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
133{
134 POSTMSG_PACKET *postmsg;
135 OSLIBPOINT point, ClientPoint;
136 Win32BaseWindow *win32wnd;
137 THDB *thdb;
138 APIRET rc = 0;
139 MSG winMsg, *pWinMsg;
140
141 //Restore our FS selector
142 SetWin32TIB();
143
144 thdb = GetThreadTHDB();
145 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
146
147 if(!thdb || (msg != WM_CREATE && win32wnd == NULL)) {
148 dprintf(("Invalid win32wnd pointer for window %x msg %x", hwnd, msg));
149 goto RunDefWndProc;
150 }
151
152 if((thdb->msgstate & 1) == 0)
153 {//message that was sent directly to our window proc handler; translate it here
154 QMSG qmsg;
155
156 qmsg.msg = msg;
157 qmsg.hwnd = hwnd;
158 qmsg.mp1 = mp1;
159 qmsg.mp2 = mp2;
160 qmsg.time = WinQueryMsgTime(thdb->hab);
161 WinQueryMsgPos(thdb->hab, &qmsg.ptl);
162 qmsg.reserved = 0;
163
164 if(OS2ToWinMsgTranslate((PVOID)thdb, &qmsg, &winMsg, FALSE, ODINMSG_NOEXTRAMSGS) == FALSE)
165 {//message was not translated
166 memset(&winMsg, 0, sizeof(MSG));
167 }
168 pWinMsg = &winMsg;
169 }
170 else {
171 pWinMsg = &thdb->msg;
172 thdb->msgstate++;
173 }
174
175 if(msg == WIN32APP_POSTMSG && (ULONG)mp1 == WIN32PM_MAGIC) {
176 //win32 app user message
177 return (MRESULT)win32wnd->PostMessage((POSTMSG_PACKET *)mp2);
178 }
179 switch( msg )
180 {
181 //OS/2 msgs
182 case WM_CREATE:
183 {
184
185 if(thdb->newWindow == 0)
186 goto createfail;
187
188 //Processing is done in after WinCreateWindow returns
189 dprintf(("OS2: WM_CREATE %x", hwnd));
190 win32wnd = (Win32BaseWindow *)thdb->newWindow;
191 thdb->newWindow = 0;
192
193 if(win32wnd->MsgCreate(WinQueryWindow(hwnd, QW_PARENT), hwnd) == FALSE)
194 {
195 RestoreOS2TIB();
196 return (MRESULT)TRUE; //discontinue window creation
197 }
198 createfail:
199 RestoreOS2TIB();
200 return (MRESULT)FALSE;
201 }
202
203 case WM_QUIT:
204 dprintf(("OS2: WM_QUIT %x", hwnd));
205 win32wnd->MsgQuit();
206 break;
207
208 case WM_CLOSE:
209 dprintf(("OS2: WM_CLOSE %x", hwnd));
210 win32wnd->MsgClose();
211 break;
212
213 case WM_DESTROY:
214 dprintf(("OS2: WM_DESTROY %x", hwnd));
215 win32wnd->MsgDestroy();
216 break;
217
218 case WM_ENABLE:
219 dprintf(("OS2: WM_ENABLE %x", hwnd));
220 win32wnd->MsgEnable(SHORT1FROMMP(mp1));
221 break;
222
223 case WM_SHOW:
224 dprintf(("OS2: WM_SHOW %x %d", hwnd, mp1));
225 win32wnd->MsgShow((ULONG)mp1);
226 break;
227
228#if 1
229 case WM_ADJUSTWINDOWPOS:
230 {
231// PSWP pswp = (PSWP)mp1;
232
233// dprintf(("OS2: WM_ADJUSTWINDOWPOS %x %x %x (%d,%d) (%d,%d)", hwnd, pswp->hwnd, pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
234 goto RunDefWndProc;
235 }
236#else
237 case WM_ADJUSTWINDOWPOS:
238 {
239 PSWP pswp = (PSWP)mp1;
240 SWP swpOld, swpNew;
241 WINDOWPOS wp;
242 ULONG parentHeight = 0;
243 HWND hParent = NULLHANDLE, hFrame = NULLHANDLE, hwndAfter;
244
245 dprintf(("OS2: WM_ADJUSTWINDOWPOS %x %x %x (%d,%d) (%d,%d)", hwnd, pswp->hwnd, pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
246
247 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) goto RunDefWndProc;;
248
249 //SvL: TODO: Workaround. Why is this happening?
250 // When this flag is set the coordinates are 0, even though SWP_SIZE & SWP_MOVE are set.
251// if ((pswp->fl & SWP_NOADJUST)) goto RunDefWndProc;
252
253 if(!win32wnd->CanReceiveSizeMsgs()) goto RunDefWndProc;;
254
255 WinQueryWindowPos(hwnd, &swpOld);
256
257 if(pswp->fl & (SWP_MOVE | SWP_SIZE)) {
258 if (win32wnd->isChild()) {
259 if(win32wnd->getParent()) {
260 hParent = win32wnd->getParent()->getOS2WindowHandle();
261 }
262 else goto RunDefWndProc;;
263 }
264 }
265 hwndAfter = pswp->hwndInsertBehind;
266 hFrame = win32wnd->getOS2FrameWindowHandle();
267 OSLibMapSWPtoWINDOWPOS(pswp, &wp, &swpOld, hParent, hFrame);
268
269 wp.hwnd = win32wnd->getWindowHandle();
270 if ((pswp->fl & SWP_ZORDER) && (pswp->hwndInsertBehind > HWND_BOTTOM))
271 {
272 Win32BaseWindow *wndAfter = Win32BaseWindow::GetWindowFromOS2Handle(pswp->hwndInsertBehind);
273 if(wndAfter) wp.hwndInsertAfter = wndAfter->getWindowHandle();
274 }
275 if(win32wnd->MsgPosChanging((LPARAM)&wp) == 0)
276 {//app or default window handler changed wp
277 dprintf(("OS2: WM_ADJUSTWINDOWPOS, app changed windowpos struct"));
278 dprintf(("%x (%d,%d), (%d,%d)", pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
279 OSLibMapWINDOWPOStoSWP(&wp, &swpNew, &swpOld, hParent, hFrame);
280 dprintf(("%x (%d,%d), (%d,%d)", swpNew.fl, swpNew.x, swpNew.y, swpNew.cx, swpNew.cy));
281 swpNew.fl |= SWP_NOADJUST;
282 swpNew.hwndInsertBehind = hwndAfter;
283 swpNew.hwnd = hFrame;
284
285 WinSetMultWindowPos(GetThreadHAB(), &swpNew, 1);
286 return (MRESULT)0;
287 }
288 break;
289 }
290#endif
291
292 case WM_WINDOWPOSCHANGED:
293 {
294 win32wnd->MsgPosChanged((LPARAM)&thdb->wp);
295 goto RunDefWndProc;
296 }
297
298 case WM_ACTIVATE:
299 {
300 HWND hwndActivate = (HWND)mp2;
301 BOOL fMinimized = FALSE;
302
303 dprintf(("OS2: WM_ACTIVATE %x %x", hwnd, hwndActivate));
304 if(WinQueryWindowULong(hwndActivate, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
305 //another (non-win32) application's window
306 //set to NULL (allowed according to win32 SDK) to avoid problems
307 hwndActivate = NULL;
308 }
309 if(WinQueryWindowULong(hwnd, QWL_STYLE) & WS_MINIMIZED)
310 {
311 fMinimized = TRUE;
312 }
313
314 win32wnd->MsgActivate(SHORT1FROMMP(mp1), fMinimized, Win32BaseWindow::OS2ToWin32Handle(hwndActivate));
315 break;
316 }
317
318 case WM_SIZE:
319 {
320 dprintf(("OS2: WM_SIZE (%d,%d) (%d,%d)", SHORT1FROMMP(mp2), SHORT2FROMMP(mp2), SHORT1FROMMP(mp1), SHORT2FROMMP(mp2)));
321 break;
322 }
323
324 case WM_MINMAXFRAME:
325 {
326 dprintf(("OS2: WM_MINMAXFRAME"));
327 break;
328 }
329
330 case WM_OWNERPOSCHANGE:
331 {
332 dprintf(("OS2: WM_OWNERPOSCHANGE"));
333 goto RunDefWndProc;
334 }
335
336 case WM_CALCVALIDRECTS:
337 {
338 dprintf(("OS2: WM_CALCVALIDRECTS"));
339 goto RunDefWndProc;
340 }
341
342 case WM_SETFOCUS:
343 {
344 HWND hwndFocus = (HWND)mp1;
345
346 dprintf(("OS2: WM_SETFOCUS %x %x %d", win32wnd->getWindowHandle(), mp1, mp2));
347 if(WinQueryWindowULong(hwndFocus, OFFSET_WIN32PM_MAGIC) != WIN32PM_MAGIC) {
348 //another (non-win32) application's window
349 //set to NULL (allowed according to win32 SDK) to avoid problems
350 hwndFocus = NULL;
351 }
352 if((ULONG)mp2 == TRUE) {
353 HWND hwndFocusWin32 = Win32BaseWindow::OS2ToWin32Handle(hwndFocus);
354 recreateCaret (hwndFocusWin32);
355 win32wnd->MsgSetFocus(hwndFocusWin32);
356 }
357 else win32wnd->MsgKillFocus(Win32BaseWindow::OS2ToWin32Handle(hwndFocus));
358 break;
359 }
360
361 //**************************************************************************
362 //Mouse messages (OS/2 Window coordinates -> Win32 coordinates relative to screen
363 //**************************************************************************
364 case WM_BUTTON1DOWN:
365 case WM_BUTTON1UP:
366 case WM_BUTTON1DBLCLK:
367 case WM_BUTTON2DOWN:
368 case WM_BUTTON2UP:
369 case WM_BUTTON2DBLCLK:
370 case WM_BUTTON3DOWN:
371 case WM_BUTTON3UP:
372 case WM_BUTTON3DBLCLK:
373 win32wnd->MsgButton(pWinMsg);
374 rc = TRUE;
375 break;
376
377 case WM_BUTTON2MOTIONSTART:
378 case WM_BUTTON2MOTIONEND:
379 case WM_BUTTON2CLICK:
380 case WM_BUTTON1MOTIONSTART:
381 case WM_BUTTON1MOTIONEND:
382 case WM_BUTTON1CLICK:
383 case WM_BUTTON3MOTIONSTART:
384 case WM_BUTTON3MOTIONEND:
385 case WM_BUTTON3CLICK:
386 goto RunDefWndProc;
387
388 case WM_MOUSEMOVE:
389 {
390 //OS/2 Window coordinates -> Win32 Window coordinates
391 win32wnd->MsgMouseMove(pWinMsg);
392 break;
393 }
394
395 case WM_CONTROL:
396 goto RunDefWndProc;
397
398 case WM_COMMAND:
399 dprintf(("OS2: WM_COMMAND %x %x %x", hwnd, mp1, mp2));
400 win32wnd->DispatchMsg(pWinMsg);
401 break;
402
403 case WM_SYSCOMMAND:
404 win32wnd->DispatchMsg(pWinMsg);
405 break;
406
407 case WM_CHAR:
408 win32wnd->DispatchMsg(pWinMsg);
409 break;
410
411 case WM_INITMENU:
412 win32wnd->MsgInitMenu(pWinMsg);
413 break;
414
415 case WM_TIMER:
416 win32wnd->DispatchMsg(pWinMsg);
417 goto RunDefWndProc;
418
419 case WM_MENUSELECT:
420 case WM_MENUEND:
421 case WM_NEXTMENU:
422 goto RunDefWndProc;
423
424 case WM_SETWINDOWPARAMS:
425 {
426 WNDPARAMS *wndParams = (WNDPARAMS *)mp1;
427
428 dprintf(("OS2: WM_SETWINDOWPARAMS %x", hwnd));
429 if(wndParams->fsStatus & WPM_TEXT) {
430 win32wnd->MsgSetText(wndParams->pszText, wndParams->cchText);
431 }
432 goto RunDefWndProc;
433 }
434
435 case WM_QUERYWINDOWPARAMS:
436 {
437 PWNDPARAMS wndpars = (PWNDPARAMS)mp1;
438 ULONG textlen;
439 PSZ wintext;
440
441 if(wndpars->fsStatus & (WPM_CCHTEXT | WPM_TEXT))
442 {
443 if(wndpars->fsStatus & WPM_CCHTEXT)
444 wndpars->cchText = win32wnd->MsgGetTextLength();
445 if(wndpars->fsStatus & WPM_TEXT)
446 wndpars->pszText = win32wnd->MsgGetText();
447
448 wndpars->fsStatus = 0;
449 wndpars->cbCtlData = 0;
450 wndpars->cbPresParams = 0;
451 RestoreOS2TIB();
452 return (MRESULT)TRUE;
453 }
454 goto RunDefWndProc;
455 }
456
457 case WM_PAINT:
458 win32wnd->DispatchMsg(pWinMsg);
459 goto RunDefWndProc;
460
461 case WM_HITTEST:
462 {
463 DWORD res;
464
465 // Only send this message if the window is enabled
466 if (!WinIsWindowEnabled(hwnd))
467 res = HT_ERROR;
468 else if (win32wnd->getIgnoreHitTest())
469 res = HT_NORMAL;
470 else
471 {
472 dprintf(("USER32: WM_HITTEST %x (%d,%d)",hwnd,(*(POINTS *)&mp1).x,(*(POINTS *)&mp1).y));
473
474 //CB: WinWindowFromPoint: PM sends WM_HITTEST -> loop -> stack overflow
475 win32wnd->setIgnoreHitTest(TRUE);
476 res = win32wnd->MsgHitTest(pWinMsg);
477 win32wnd->setIgnoreHitTest(FALSE);
478 }
479 RestoreOS2TIB();
480 return (MRESULT)res;
481 }
482
483 case WM_CONTEXTMENU:
484 {
485 win32wnd->DispatchMsg(pWinMsg);
486
487 RestoreOS2TIB();
488 return (MRESULT)TRUE;
489 }
490
491 case WM_ERASEBACKGROUND:
492 {
493 dprintf(("OS2: WM_ERASEBACKGROUND %x", win32wnd->getWindowHandle()));
494 break;
495 }
496
497 case WM_FOCUSCHANGE:
498 dprintf(("OS2: WM_FOCUSCHANGE %x", win32wnd->getWindowHandle()));
499 goto RunDefWndProc;
500
501 case WM_SYSCOLORCHANGE:
502 case WM_SYSVALUECHANGED:
503 case WM_SETSELECTION:
504 case WM_PPAINT:
505 case WM_PSETFOCUS:
506 case WM_PSYSCOLORCHANGE:
507 case WM_PSIZE:
508 case WM_PACTIVATE:
509 case WM_PCONTROL:
510 case WM_HELP:
511 case WM_APPTERMINATENOTIFY:
512 case WM_PRESPARAMCHANGED:
513 case WM_DRAWITEM:
514 case WM_MEASUREITEM:
515 case WM_CONTROLPOINTER:
516 case WM_QUERYDLGCODE:
517 case WM_SUBSTITUTESTRING:
518 case WM_MATCHMNEMONIC:
519 case WM_SAVEAPPLICATION:
520 case WM_SEMANTICEVENT:
521 default:
522 //dprintf(("OS2: RunDefWndProc msg %x for %x", msg, hwnd));
523 RestoreOS2TIB();
524 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
525 }
526 RestoreOS2TIB();
527 return (MRESULT)rc;
528
529RunDefWndProc:
530// dprintf(("OS2: RunDefWndProc msg %x for %x", msg, hwnd));
531 RestoreOS2TIB();
532
533 return WinDefWindowProc( hwnd, msg, mp1, mp2 );
534} /* End of Win32WindowProc */
535//******************************************************************************
536//******************************************************************************
537MRESULT EXPENTRY Win32SubclassWindowProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
538{
539 Win32BaseWindow* win32wnd;
540
541 //Restore our FS selector
542 SetWin32TIB();
543
544 win32wnd = Win32BaseWindow::GetWindowFromOS2Handle(hwnd);
545
546 if (!win32wnd)
547 {
548 dprintf(("Invalid win32wnd pointer for subclassed window %x!!", hwnd));
549 goto RunDefWndProc;
550 }
551
552 switch (msg)
553 {
554 case WM_WINDOWPOSCHANGED:
555 {
556 PSWP pswp = (PSWP)mp1;
557 SWP swpOld = *(pswp + 1);
558 WINDOWPOS wp;
559 HWND hParent = NULLHANDLE, hFrame = NULLHANDLE;
560
561 dprintf(("OS2Subclass: WM_WINDOWPOSCHANGED %x %x (%d,%d) (%d,%d)", hwnd, pswp->fl, pswp->x, pswp->y, pswp->cx, pswp->cy));
562 if ((pswp->fl & (SWP_SIZE | SWP_MOVE | SWP_ZORDER)) == 0) break;
563
564 hParent = hFrame = WinQueryWindow(hwnd, QW_PARENT);
565
566 OSLibMapSWPtoWINDOWPOS(pswp,&wp, &swpOld,hParent,hFrame);
567
568 win32wnd->setWindowRect(swpOld.x, swpOld.y, swpOld.x + swpOld.cx, swpOld.y + swpOld.cy);
569 win32wnd->setClientRect(swpOld.x, swpOld.y, swpOld.x + swpOld.cx, swpOld.y + swpOld.cy);
570 wp.x = swpOld.x;
571 wp.y = swpOld.y;
572 wp.cx = swpOld.cx;
573 wp.cy = swpOld.cy;
574
575 wp.hwnd = win32wnd->getWindowHandle();
576
577 win32wnd->MsgPosChanged((LPARAM)&wp);
578
579 goto RunOldWndProc;
580 }
581
582 default:
583 goto RunDefHandler;
584 }
585
586RunDefWndProc:
587 RestoreOS2TIB();
588 return WinDefWindowProc(hwnd,msg,mp1,mp2);
589
590RunOldWndProc:
591 RestoreOS2TIB();
592 return ((PFNWP)win32wnd->getOldWndProc())(hwnd,msg,mp1,mp2);
593
594RunDefHandler:
595 RestoreOS2TIB();
596 return Win32WindowProc(hwnd,msg,mp1,mp2);
597}
598
599PVOID SubclassWithDefHandler(HWND hwnd)
600{
601 return WinSubclassWindow(hwnd,Win32SubclassWindowProc);
602}
Note: See TracBrowser for help on using the repository browser.