source: trunk/hook/lswhook.c@ 82

Last change on this file since 82 was 82, checked in by Gregg Young, 10 years ago

This commit is to allow me acces to my bleeding edge code at warpstock. Don't build this commit unless you are very familiar with lswitcher. It will work but is not ready for prime time.

File size: 21.1 KB
Line 
1/*
2 * Copyright (C) 1997-2006 Andrei Los.
3 * This file is part of the lSwitcher source package.
4 * lSwitcher is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation, in version 2 as it comes in the
7 * "COPYING" file of the lSwitcher main distribution.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define INCL_DOSMEMMGR
15#define INCL_DOSMODULEMGR
16#define INCL_WIN
17
18#include "lswitch.h"
19#include "taskbar.h"
20#include <string.h>
21#include <stdio.h>
22#define __PMPRINTF__
23#include "PMPRINTF.H"
24
25/*
26 Since the hooks may be called in the context of any thead having a message
27 queue, we must use shared memory to access the globals of lSwitcher daemon.
28 For the same reason the shared mem must be freed upon exiting the hook procs,
29 otherwise the caller will retain a reference to it and the shared mem object
30 will not be destroyed when lSwitcher exits
31 IMPORTANT !!! Don't use DosGetNamedSharedMed/DosFreeMem before it's REALLY
32 needed, check all other conditions first. These functions turn out to be
33 expensive performance-wise
34
35 With version 2.6 this DLL, if compiled with Watcom C, does not use C RTL
36 (since Watcom RTL does not support multiple processes attached to a DLL
37 with a single data segment, which we need). Because of this stack overflow
38 is not checked for, and we want to reduce stack usage to a minimum
39*/
40
41HWND hwndMenuUp = NULLHANDLE, hwndTskBar = NULLHANDLE, hwndPopup = NULLHANDLE;
42BOOL bWidget;
43
44APIRET ctrpDesktopWorkareaSupported(VOID);
45
46APIRET doshQueryProcAddr(PCSZ pcszModuleName, ULONG ulOrdinal, PFN *ppfn);
47
48//#ifndef XWORKPLACE
49/*
50 * WinSetDesktopWorkArea:
51 * undocumented Warp 4 API to change the "desktop work
52 * area", which, among other things, sets the size for
53 * maximized windows.
54 *
55 * This is manually imported from PMMERGE.5468.
56 */
57
58BOOL APIENTRY WinSetDesktopWorkArea(HWND hwndDesktop,
59 PRECTL pwrcWorkArea);
60typedef BOOL APIENTRY WINSETDESKTOPWORKAREA(HWND hwndDesktop,
61 PRECTL pwrcWorkArea);
62typedef WINSETDESKTOPWORKAREA *PWINSETDESKTOPWORKAREA;
63
64/*
65 * WinQueryDesktopWorkArea:
66 * the reverse to the above.
67 *
68 * This is manually imported from PMMERGE.5469.
69 */
70
71BOOL APIENTRY WinQueryDesktopWorkArea(HWND hwndDesktop,
72 PRECTL pwrcWorkArea);
73typedef BOOL APIENTRY WINQUERYDESKTOPWORKAREA(HWND hwndDesktop,
74 PRECTL pwrcWorkArea);
75typedef WINQUERYDESKTOPWORKAREA *PWINQUERYDESKTOPWORKAREA;
76
77static PWINSETDESKTOPWORKAREA G_WinSetDesktopWorkArea = (PWINSETDESKTOPWORKAREA)-1;
78static PWINQUERYDESKTOPWORKAREA G_WinQueryDesktopWorkArea = (PWINQUERYDESKTOPWORKAREA)-1;
79
80BOOL fWorkAreaSupported;
81/**
82 * Check to see if PMMerge supports reducing the desktop
83 * Code adapted from xworkplace by Ulrich M”ller & Paul Ratcliffe
84 **/
85APIRET doshQueryProcAddr(PCSZ pcszModuleName, // in: module name (e.g. "PMMERGE")
86 ULONG ulOrdinal, // in: proc ordinal
87 PFN *ppfn) // out: proc address
88{
89 HMODULE hmod;
90 APIRET arc;
91 if (!(arc = DosQueryModuleHandle((PSZ)pcszModuleName,
92 &hmod)))
93 {
94 if ((arc = DosQueryProcAddr(hmod,
95 ulOrdinal,
96 NULL,
97 ppfn)))
98 {
99 // the CP programming guide and reference says use
100 // DosLoadModule if DosQueryProcAddr fails with this error
101 if (arc == ERROR_INVALID_HANDLE)
102 {
103 if (!(arc = DosLoadModule(NULL,
104 0,
105 (PSZ)pcszModuleName,
106 &hmod)))
107 {
108 arc = DosQueryProcAddr(hmod,
109 ulOrdinal,
110 NULL,
111 ppfn);
112 }
113 }
114 }
115 }
116
117 return arc;
118}
119/**
120 * Check to see if PMMerge supports reducing the desktop
121 * Code adapted from xworkplace by Ulrich M”ller & Paul Ratcliffe
122 **/
123APIRET ctrpDesktopWorkareaSupported(VOID)
124{
125 APIRET arc = ERROR_INVALID_ORDINAL;
126
127 if ((ULONG)G_WinSetDesktopWorkArea == -1)
128 {
129 // first call:
130 if ( (!(arc = doshQueryProcAddr("PMMERGE",
131 5468,
132 (PFN*)&G_WinSetDesktopWorkArea)))
133 && (!(arc = doshQueryProcAddr("PMMERGE",
134 5469,
135 (PFN*)&G_WinQueryDesktopWorkArea)))
136 )
137 {
138 //lstInit(&G_llWorkAreaViews, FALSE);
139 fWorkAreaSupported = TRUE;
140 }
141 }
142
143 if (arc)
144 {
145 G_WinSetDesktopWorkArea = NULL;
146 G_WinQueryDesktopWorkArea = NULL;
147 }
148
149 return arc;
150}
151
152//simple and dirty string to integer conversion
153/*ULONG __atol(UCHAR * s)
154{
155 SHORT k;
156 ULONG r, base;
157
158 for (k = 0; s[k] != '\0'; k++) ;
159 for (--k, base = 1, r = 0; k >= 0; k--, base *= 10)
160 r += (s[k] - 48) * base;
161
162 return r;
163} */
164
165BOOL IsWindowClass(HWND hwnd, UCHAR * pszClassName)
166{
167 static UCHAR ucBuf[32]; //reduce stack usage to minimum since we don't use stack probes
168 USHORT k;
169 BOOL bEqual;
170
171 WinQueryClassName(hwnd, sizeof(ucBuf) - 1, ucBuf);
172/* equivalent of strcmp, but we don't want to use the RTL */
173 for (k = 0, bEqual = TRUE; ucBuf[k] != '\0' && pszClassName[k] != '\0';
174 k++)
175 if (ucBuf[k] != pszClassName[k]) {
176 bEqual = FALSE;
177 break;
178 }
179
180 return (bEqual && ucBuf[k] == '\0' && pszClassName[k] == '\0');
181}
182
183BOOL IsDesktop(HWND hwnd)
184{
185 return (hwnd == WinQueryWindow(HWND_DESKTOP, QW_BOTTOM) &&
186 (IsWindowClass(hwnd, "wpFolder window")));
187}
188
189BOOL GetSharedMem(LSWDATA ** plswData)
190{
191 return
192 (DosGetNamedSharedMem
193 ((PVOID *) plswData, SHAREMEM_NAME, PAG_READ | PAG_WRITE) == 0
194 && plswData != NULL);
195}
196
197VOID SetPrty(ULONG pid, USHORT usPrty)
198{
199 SHORT sPrtyC, sPrtyD;
200 BOOL bDesc;
201
202 bDesc = (usPrty & 0x8000);
203 usPrty &= ~0x8000;
204 sPrtyC = (usPrty + PRTYD_MAXIMUM) >> 8;
205 sPrtyD = usPrty - (sPrtyC << 8);
206 DosSetPriority(bDesc ? PRTYS_PROCESSTREE : PRTYS_PROCESS, sPrtyC, sPrtyD,
207 pid);
208}
209
210BOOL EXPENTRY lswInputHook(HAB hab, PQMSG pQmsg, ULONG fs)
211{
212 LSWDATA *plswData;
213 POINTL ptl;
214 static BOOL bOnTop = FALSE;
215 static USHORT usOldY = 0xFFFF, cyScreen = 0, cyTskBar = 0; // this and the previous lines need to be static
216 static RECTL rcl; //reduce stack usage to minimum since we don't use stack probes
217 static HWND hwndBtn = 0;
218 PPIB ppib;
219
220 DosGetInfoBlocks(NULL, &ppib);
221 if (ppib->pib_flstatus & PS_EXITLIST)
222 return FALSE;
223
224 if (cyScreen == 0 || pQmsg->msg == WM_SYSVALUECHANGED)
225 cyScreen = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
226
227// get taskbar hwnd in case it changed
228 if (pQmsg->msg == WM_NULL && pQmsg->hwnd == 0 && GetSharedMem(&plswData)) {
229 hwndTskBar = plswData->hwndTaskBarClient;
230 DosFreeMem(plswData);
231 }
232
233 if (pQmsg->msg == WM_MOUSEMOVE) {
234 if (pQmsg->hwnd != hwndBtn) {
235 if (WinQueryWindow(pQmsg->hwnd, QW_PARENT) == hwndTskBar
236 && IsWindowClass(pQmsg->hwnd, "#3")) {
237 hwndBtn = pQmsg->hwnd;
238 WinPostMsg(hwndTskBar, LSWM_MOUSEOVERBTN, MPFROMHWND(hwndBtn),
239 0);
240 }
241 else if (hwndBtn != 0) {
242 hwndBtn = 0;
243 WinPostMsg(hwndTskBar, LSWM_MOUSEOVERBTN, MPFROMHWND(hwndBtn),
244 0);
245 }
246 }
247
248 if (!bWidget && hwndMenuUp == NULLHANDLE
249 && (WinQueryPointerPos(HWND_DESKTOP, &ptl), ptl.y != usOldY)) {
250 usOldY = ptl.y;
251 if ((!bOnTop && (ptl.y == 0 || ptl.y == cyScreen - 1)) ||
252 (bOnTop && ptl.y > 2 * cyTskBar
253 && ptl.y < cyScreen - 2 * cyTskBar)) {
254
255 if (!GetSharedMem(&plswData))
256 return FALSE;
257 if ((!bOnTop
258 && plswData->Settings.bTaskBarTopScr ^ ptl.y == 0)
259 || (bOnTop && !WinIsWindowVisible(plswData->hwndMenu))) {
260 if (!bOnTop) {
261 WinQueryWindowRect(plswData->hwndTaskBar, &rcl);
262 cyTskBar = rcl.yTop;
263 }
264 WinSetWindowPos(plswData->hwndTaskBar,
265 HWND_TOP, 0, 0, 0,
266 0, SWP_ZORDER | SWP_SHOW);
267 bOnTop ^= TRUE;
268 }
269 DosFreeMem(plswData);
270 }
271 }
272 }
273 else if (pQmsg->msg ==
274 WinFindAtom(WinQuerySystemAtomTable(), LSWM_GETPROCCMD)
275 && GetSharedMem(&plswData)) {
276 UCHAR *ucHandle;
277 USHORT usHandle = 0;
278
279 strncpy(plswData->buf,
280 &ppib->pib_pchcmd[strlen(ppib->pib_pchcmd) + 1],
281 sizeof plswData->buf);
282 if (DosScanEnv("WP_OBJHANDLE", &ucHandle) == 0 && ucHandle != NULL)
283 strncpy(&plswData->buf[strlen(plswData->buf) + 1], ucHandle,
284 sizeof plswData->buf - strlen(plswData->buf) - 2);
285
286 DosFreeMem(plswData);
287 WinPostMsg(hwndTskBar, LSWM_SWITCHLISTCHANGED, MPFROMLONG(4),
288 pQmsg->mp2);
289 //don't understand why we need to pass this over, but there is some system instability otherwise
290 }
291 else if (pQmsg->msg ==
292 WinFindAtom(WinQuerySystemAtomTable(), LSWM_SETPRIORITY)) {
293 SetPrty(LONGFROMMP(pQmsg->mp2), SHORT1FROMMP(pQmsg->mp1));
294 return TRUE;
295 }
296 return FALSE;
297}
298
299/* we install this function as a pre-accelerator hook (undocumented). This hook
300 is called even before an application accelerator table is translated, which helps
301 to avoid compatibility problems with Ctrl-Tab hotkey */
302BOOL EXPENTRY lswPreAccHook(HAB hab, PQMSG pQmsg, ULONG fs)
303{
304 USHORT usFlags;
305 UCHAR ucScan;
306 LSWDATA *plswData;
307 BOOL bRet;
308 PPIB ppib;
309
310 DosGetInfoBlocks(NULL, &ppib);
311 if (ppib->pib_flstatus & PS_EXITLIST)
312 return FALSE;
313
314 if (pQmsg->msg != WM_CHAR
315 || (usFlags = SHORT1FROMMP(pQmsg->mp1), ucScan =
316 CHAR4FROMMP(pQmsg->mp1), (usFlags & KC_SCANCODE)) == 0)
317 return FALSE;
318
319 bRet = FALSE;
320/* tab w/ left Ctrl down. Trap the key either it's pressed or released,
321 so that it does not reach other applications and trigger something*/
322/* Alt-Tab might work in alternative shells */
323 if (ucScan == SCAN_TAB
324 && ((usFlags & KC_CTRL) != 0 ^ (usFlags & KC_ALT) != 0)
325 && GetSharedMem(&plswData)) {
326 if ((plswData->Settings.ucPopupHotKey == 0 && (usFlags & KC_ALT))
327 || (plswData->Settings.ucPopupHotKey == 1 && (usFlags & KC_CTRL))) {
328 if (usFlags & KC_KEYUP)
329 WinPostMsg(plswData->hwndPopClient, WM_COMMAND, MPFROMSHORT
330 ((usFlags & KC_SHIFT) ? CMD_SCROLLLEFT :
331 CMD_SCROLLRIGHT), MPFROM2SHORT(CMDSRC_OTHER,
332 FALSE));
333 bRet = TRUE;
334 }
335 DosFreeMem(plswData);
336 }
337
338/* Show settings */
339 if (!(usFlags & KC_KEYUP) && (usFlags & KC_ALT) && (usFlags & KC_CTRL)
340 && GetSharedMem(&plswData)) {
341 if (ucScan == plswData->Settings.ucSettingsScan) {
342 WinPostMsg(plswData->hwndPopClient, WM_COMMAND,
343 MPFROMSHORT(CMD_SHOWSETTINGS),
344 MPFROM2SHORT(CMDSRC_OTHER, FALSE));
345 bRet = TRUE;
346 }
347 DosFreeMem(plswData);
348 }
349
350 return bRet;
351}
352
353VOID EXPENTRY lswSendHook(HAB hab, PSMHSTRUCT psmh, BOOL fInterTask)
354{
355 LSWDATA *plswData;
356 HSWITCH hsw;
357 static SWCNTRL swctl; //reduce stack usage to a minimum since we don't use stack probes
358 static SWP swp;
359 ULONG ulFlags;
360 BOOL bPosChange, bActiveChange;
361 PPIB ppib;
362
363 if (psmh->msg == SH_SWITCHLIST && IsWindowClass(psmh->hwnd, "WindowList") && //check msg target to avoid multiple messages
364 (((LONG) psmh->mp1 >= 1 && (LONG) psmh->mp1 <= 3)
365 || (LONG) psmh->mp1 == 0x10001) && GetSharedMem(&plswData)) {
366 if (plswData->bNowActive)
367 WinPostMsg(plswData->hwndPopClient, LSWM_SWITCHLISTCHANGED,
368 psmh->mp1, psmh->mp2);
369 if (plswData->Settings.bTaskBarOn)
370 WinPostMsg(plswData->hwndTaskBarClient, LSWM_SWITCHLISTCHANGED,
371 psmh->mp1, psmh->mp2);
372 if (WinIsWindow(hab, plswData->hwndParamDlg))
373 WinPostMsg(plswData->hwndParamDlg, LSWM_SWITCHLISTCHANGED,
374 psmh->mp1, psmh->mp2);
375 DosFreeMem(plswData);
376 return;
377 }
378
379 DosGetInfoBlocks(NULL, &ppib);
380 if (ppib->pib_flstatus & PS_EXITLIST)
381 return;
382
383 if (psmh->msg == WM_COMMAND && IsWindowClass(psmh->hwnd, "AltTabWindow") && (WinGetPhysKeyState(HWND_DESKTOP, 0x5e) & 0x8000) == 0 && // right Alt up
384 GetSharedMem(&plswData)) {
385 if (plswData->Settings.ucPopupHotKey == 0
386 && plswData->Settings.bPMSwitcher) {
387 BOOL bShift = (WinGetPhysKeyState(HWND_DESKTOP, 0x2a) & 0x8000) || // either Shift down
388 (WinGetPhysKeyState(HWND_DESKTOP, 0x36) & 0x8000);
389
390 WinPostMsg(plswData->hwndPopClient, WM_COMMAND,
391 MPFROMSHORT(bShift ? CMD_SCROLLLEFT : CMD_SCROLLRIGHT),
392 MPFROM2SHORT(CMDSRC_OTHER, FALSE));
393 psmh->msg = WM_NULL;
394 }
395 DosFreeMem(plswData);
396 return;
397 }
398
399// make sure the taskbar does not show up and cover desktop menu
400 if (psmh->msg == WM_INITMENU && IsDesktop(psmh->hwnd))
401 hwndMenuUp = HWNDFROMMP(psmh->mp2);
402 if (psmh->msg == WM_MENUEND && HWNDFROMMP(psmh->mp2) == hwndMenuUp)
403 hwndMenuUp = NULLHANDLE;
404
405 if (psmh->msg == WM_SETICON && WinQuerySwitchHandle(psmh->hwnd, 0) != 0 &&
406 GetSharedMem(&plswData)) {
407 if (plswData->bNowActive)
408 WinPostMsg(plswData->hwndPopClient, LSWM_WNDICONCHANGED,
409 psmh->mp1, MPFROMHWND(psmh->hwnd));
410 if (plswData->Settings.bTaskBarOn)
411 WinPostMsg(plswData->hwndTaskBarClient, LSWM_WNDICONCHANGED,
412 psmh->mp1, MPFROMHWND(psmh->hwnd));
413 DosFreeMem(plswData);
414 return;
415 }
416
417 /* make just minimized or hidden window appear after the current one in
418 the switch list if the corresponding option is on in settings */
419 if (psmh->msg == WM_ADJUSTFRAMEPOS &&
420 (((PSWP) PVOIDFROMMP(psmh->mp1))->fl & (SWP_HIDE | SWP_MINIMIZE)) &&
421 !(WinGetPhysKeyState(HWND_DESKTOP, 0x38) & 0x8000) &&
422 WinQuerySwitchHandle(psmh->hwnd, 0) != 0
423 && IsWindowClass(psmh->hwnd, "#1") && GetSharedMem(&plswData)) {
424
425 if (plswData->Settings.bChangeZOrder)
426 ((PSWP) PVOIDFROMMP(psmh->mp1))->hwndInsertBehind = HWND_TOP;
427 DosFreeMem(plswData);
428 return;
429 }
430
431 if (psmh->msg == WM_DESTROY
432 && WinQueryWindow(psmh->hwnd, QW_PARENT) == WinQueryDesktopWindow(0,
433 0)
434 && GetSharedMem(&plswData)) {
435 USHORT k;
436
437//the minimized window list holds the virtual desktop positions the windows were minimized from
438 for (k = 0; k < MINMAXITEMS; k++)
439 if (psmh->hwnd == plswData->MinMaxWnd[2 * k]) {
440 plswData->MinMaxWnd[2 * k] = 0;
441 break;
442 }
443 DosFreeMem(plswData);
444 return;
445 }
446
447 if (psmh->msg == WM_MINMAXFRAME
448 && WinQueryWindow(psmh->hwnd, QW_PARENT) == WinQueryDesktopWindow(0,
449 0)
450 && GetSharedMem(&plswData)) {
451
452 USHORT k;
453
454 ulFlags = ((PSWP) PVOIDFROMMP(psmh->mp1))->fl;
455 WinQueryWindowPos(psmh->hwnd, &swp);
456
457//the minimized window list holds the virtual desktop positions the windows were minimized from
458 for (k = 0; k < MINMAXITEMS; k++)
459 if ((ulFlags & SWP_MAXIMIZE)
460 && psmh->hwnd == plswData->MinMaxWnd[2 * k]) {
461 ((PSWP) PVOIDFROMMP(psmh->mp1))->x +=
462 (WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN) +
463 8) * (((plswData->MinMaxWnd[2 * k + 1] & 0xFF00) >> 8) -
464 ((plswData->lCurrDesktop & 0xFF00) >> 8));
465 ((PSWP) PVOIDFROMMP(psmh->mp1))->y +=
466 (WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) +
467 8) * ((plswData->MinMaxWnd[2 * k + 1] & 0xFF) -
468 (plswData->lCurrDesktop & 0xFF));
469 plswData->MinMaxWnd[2 * k] = 0;
470 break;
471 }
472 else if ((ulFlags & SWP_MINIMIZE) && (swp.fl & SWP_MAXIMIZE)
473 && plswData->MinMaxWnd[2 * k] == 0) {
474 plswData->MinMaxWnd[2 * k] = psmh->hwnd;
475 plswData->MinMaxWnd[2 * k + 1] = plswData->lCurrDesktop;
476 break;
477 }
478 DosFreeMem(plswData);
479 return;
480 }
481
482/* can't call WinPostMsg in WM_ACTIVATE hook because of some random crashes
483 if (!bWidget && psmh->msg==WM_ACTIVATE) {
484 WinPostMsg(hwndTskBar,LSWM_ACTIVEWNDCHANGED,0,0);
485 return;
486 }
487*/
488
489 if (psmh->msg == WM_WINDOWPOSCHANGED &&
490 (ulFlags = ((PSWP) PVOIDFROMMP(psmh->mp1))->fl,
491 bPosChange =
492 (ulFlags &
493 (SWP_HIDE | SWP_SHOW | SWP_MINIMIZE | SWP_MAXIMIZE | SWP_RESTORE)),
494 bActiveChange =
495 (ulFlags &
496 (SWP_ACTIVATE | SWP_DEACTIVATE | SWP_FOCUSACTIVATE |
497 SWP_FOCUSDEACTIVATE)), (bPosChange
498 && (hsw =
499 WinQuerySwitchHandle(psmh->hwnd,
500 0)) != 0
501 && (WinQuerySwitchEntry(hsw, &swctl),
502 swctl.hwnd == psmh->hwnd))
503 || bActiveChange) && GetSharedMem(&plswData)) {
504
505//notify the lswitcher app of window state changes
506 if (plswData->Settings.bTaskBarOn && bActiveChange)
507 WinPostMsg(plswData->hwndTaskBarClient, LSWM_ACTIVEWNDCHANGED,
508 MPFROMHWND(psmh->hwnd), psmh->mp1);
509 if (bPosChange) {
510 WinPostMsg(plswData->hwndPopClient, LSWM_WNDSTATECHANGED,
511 MPFROM2SHORT(hsw & 0xFFFF, (SHORT) (ulFlags & 0xFFFF)),
512 MPFROMHWND(psmh->hwnd));
513 if (plswData->Settings.bTaskBarOn)
514 WinPostMsg(plswData->hwndTaskBarClient, LSWM_WNDSTATECHANGED,
515 MPFROM2SHORT(hsw & 0xFFFF,
516 (SHORT) (ulFlags & 0xFFFF)),
517 MPFROMHWND(psmh->hwnd));
518 }
519 DosFreeMem(plswData);
520 return;
521 }
522}
523
524LONG EXPENTRY lswHookInit(LSWDATA * plswData)
525{
526 bWidget = plswData->bWidget;
527
528 hwndTskBar = plswData->hwndTaskBarClient;
529 hwndPopup = plswData->hwndPopClient;
530
531 if (DosQueryModuleHandle(DLL_NAME, &plswData->hmodHook))
532 return -1;
533
534 if (!WinSetHook
535 (plswData->hab, NULLHANDLE, HK_SENDMSG, (PFN) lswSendHook,
536 plswData->hmodHook))
537 return -2;
538 if (!WinSetHook
539 (plswData->hab, NULLHANDLE, HK_PREACCEL, (PFN) lswPreAccHook,
540 plswData->hmodHook))
541 return -3;
542 if (!WinSetHook
543 (plswData->hab, NULLHANDLE, HK_INPUT, (PFN) lswInputHook,
544 plswData->hmodHook))
545 return -4;
546
547 WinPostMsg(0, WM_NULL, 0, 0); //reset the hook
548
549 return MAKEULONG(MAKEUSHORT(VERSIONMAJOR, VERSIONMINOR),
550 MAKEUSHORT(REVISION, 0));
551}
552
553VOID EXPENTRY lswHookTerm(LSWDATA * plswData)
554{
555 WinReleaseHook(plswData->hab, NULLHANDLE, HK_INPUT, (PFN) lswInputHook,
556 plswData->hmodHook);
557 WinReleaseHook(plswData->hab, NULLHANDLE, HK_PREACCEL,
558 (PFN) lswPreAccHook, plswData->hmodHook);
559 WinReleaseHook(plswData->hab, NULLHANDLE, HK_SENDMSG, (PFN) lswSendHook,
560 plswData->hmodHook);
561}
562
563ULONG EXPENTRY lswHookGetVersion(void)
564{
565 return MAKEULONG(MAKEUSHORT(VERSIONMAJOR, VERSIONMINOR),
566 MAKEUSHORT(REVISION, 0));
567}
568/**
569 * Update the desktop area as appropriate
570 * Code adapted from xworkplace by Ulrich M”ller & Paul Ratcliffe
571 **/
572BOOL EXPENTRY UpdateDesktopWorkarea(LSWDATA * plswData,
573 BOOL fForceFullSize) // in: if TRUE, desktop made full size
574{
575 BOOL brc = FALSE;
576 static BOOL didOnce = FALSE;
577
578 if (!didOnce) {
579 ctrpDesktopWorkareaSupported();
580 didOnce = TRUE;
581 }
582 // workareas supported on this system?
583 if (fWorkAreaSupported)
584 {
585 /*
586 * (2) Calculate new desktop workarea:
587 *
588 */
589 RECTL rclCurrent, rclNew;
590 ULONG ulCutBottom = 0, ulCutTop = 0,
591 // take frame sizing border into account
592 cyFrame = WinQuerySysValue(HWND_DESKTOP, SV_CYSIZEBORDER);
593 // get current first
594 G_WinQueryDesktopWorkArea(HWND_DESKTOP, &rclCurrent);
595 // compose new workarea; start out with screen size
596 rclNew.xLeft = 0;
597 rclNew.yBottom = 0;
598 rclNew.xRight = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
599 rclNew.yTop = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
600 // the workarea APIs want inclusive rectangles...
601 // I tested this, I get 1024 and 768 for the top right.
602
603 if (!fForceFullSize) {
604 if (!plswData->Settings.bTaskBarTopScr)
605 {
606 // on bottom:
607 if (plswData->Settings.sTskBarCY + cyFrame > ulCutBottom)
608 ulCutBottom = plswData->Settings.sTskBarCY + cyFrame;
609 }
610 else
611 // on top:
612 if (plswData->Settings.sTskBarCY + cyFrame - 1 > ulCutTop)
613 ulCutTop = plswData->Settings.sTskBarCY + cyFrame - 1;
614 rclNew.yBottom += ulCutBottom;
615 rclNew.yTop -= ulCutTop;
616 }
617
618 if (memcmp(&rclCurrent, &rclNew, sizeof(RECTL)) != 0)
619 {
620 // rectangle has changed:
621
622 /*
623 * (3) Set new desktop workarea:
624 *
625 */
626
627 G_WinSetDesktopWorkArea(HWND_DESKTOP, &rclNew);
628
629 brc = TRUE;
630 }
631
632 } // end if (fWorkAreaSupported)
633
634 return brc;
635}
636
Note: See TracBrowser for help on using the repository browser.