/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1145 by ossman_, Thu Mar 16 13:24:18 2006 UTC revision 1449 by astrand, Tue Mar 11 08:21:33 2008 UTC
# Line 4  Line 4 
4    
5     Based on code copyright (C) 2004-2005 Martin Wickett     Based on code copyright (C) 2004-2005 Martin Wickett
6    
7     Copyright (C) Peter Åstrand <astrand@cendio.se> 2005-2006     Copyright 2005-2008 Peter Åstrand <astrand@cendio.se> for Cendio AB
8     Copyright (C) Pierre Ossman <ossman@cendio.se> 2006     Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
9    
10     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 22  Line 22 
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */  */
24    
25    #include <assert.h>
26  #include <stdio.h>  #include <stdio.h>
27  #include <stdarg.h>  #include <stdarg.h>
28    
# Line 45  Line 46 
46  int g_instance_count SHARED = 0;  int g_instance_count SHARED = 0;
47    
48  // blocks for locally generated events  // blocks for locally generated events
49    HWND g_block_move_hwnd SHARED = NULL;
50    unsigned int g_block_move_serial SHARED = 0;
51  RECT g_block_move SHARED = { 0, 0, 0, 0 };  RECT g_block_move SHARED = { 0, 0, 0, 0 };
52    
53    unsigned int g_blocked_zchange_serial SHARED = 0;
54    HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
55    
56    unsigned int g_blocked_focus_serial SHARED = 0;
57    HWND g_blocked_focus SHARED = NULL;
58    
59    unsigned int g_blocked_state_serial SHARED = 0;
60    HWND g_blocked_state_hwnd SHARED = NULL;
61    int g_blocked_state SHARED = -1;
62    
63  #pragma data_seg ()  #pragma data_seg ()
64    
65  #pragma comment(linker, "/section:SHAREDDATA,rws")  #pragma comment(linker, "/section:SHAREDDATA,rws")
66    
67    #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
68    static UINT g_wm_seamless_focus;
69    
70  static HHOOK g_cbt_hook = NULL;  static HHOOK g_cbt_hook = NULL;
71  static HHOOK g_wndproc_hook = NULL;  static HHOOK g_wndproc_hook = NULL;
72  static HHOOK g_wndprocret_hook = NULL;  static HHOOK g_wndprocret_hook = NULL;
# Line 59  static HINSTANCE g_instance = NULL; Line 75  static HINSTANCE g_instance = NULL;
75    
76  static HANDLE g_mutex = NULL;  static HANDLE g_mutex = NULL;
77    
78    static BOOL
79    is_toplevel(HWND hwnd)
80    {
81            BOOL toplevel;
82            HWND parent;
83            parent = GetAncestor(hwnd, GA_PARENT);
84    
85            /* According to MS: "A window that has no parent, or whose
86               parent is the desktop window, is called a top-level
87               window." See http://msdn2.microsoft.com/en-us/library/ms632597(VS.85).aspx. */
88            toplevel = (!parent || parent == GetDesktopWindow());
89            return toplevel;
90    }
91    
92    /* Returns true if a window is a menu window. */
93    static BOOL
94    is_menu(HWND hwnd)
95    {
96            HWND owner = GetWindow(hwnd, GW_OWNER);
97            LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
98            return (exstyle & (WS_EX_TOOLWINDOW | WS_EX_TOPMOST)) && owner;
99    
100    }
101    
102    /* Determine the "parent" field for the CREATE response. */
103    static HWND
104    get_parent(HWND hwnd)
105    {
106            HWND result;
107            HWND owner;
108            LONG exstyle;
109    
110            /* Use the same logic to determine if the window should be
111               "transient" (ie have no task icon) as MS uses. This is documented at
112               http://msdn2.microsoft.com/en-us/library/bb776822.aspx */
113            owner = GetWindow(hwnd, GW_OWNER);
114            exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
115            if (!owner && !(exstyle & WS_EX_TOOLWINDOW))
116            {
117                    /* display taskbar icon */
118                    result = NULL;
119            }
120            else
121            {
122                    /* no taskbar icon */
123                    if (owner)
124                            result = owner;
125                    else
126                            result = (HWND) - 1;
127            }
128    
129            return result;
130    }
131    
132  static void  static void
133  update_position(HWND hwnd)  update_position(HWND hwnd)
134  {  {
135          RECT rect, blocked;          RECT rect, blocked;
136            HWND blocked_hwnd;
137            unsigned int serial;
138    
139            WaitForSingleObject(g_mutex, INFINITE);
140            blocked_hwnd = g_block_move_hwnd;
141            serial = g_block_move_serial;
142            memcpy(&blocked, &g_block_move, sizeof(RECT));
143            ReleaseMutex(g_mutex);
144    
145            vchannel_block();
146    
147          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
148          {          {
149                  debug("GetWindowRect failed!\n");                  debug("GetWindowRect failed!\n");
150                  return;                  goto end;
151          }          }
152    
153            if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
154                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
155                    goto end;
156    
157            vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
158                           hwnd,
159                           rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
160    
161          end:
162            vchannel_unblock();
163    }
164    
165    static void
166    update_zorder(HWND hwnd)
167    {
168            HWND behind;
169            HWND block_hwnd, block_behind;
170            unsigned int serial;
171    
172          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
173          memcpy(&blocked, &g_block_move, sizeof(RECT));          serial = g_blocked_zchange_serial;
174            block_hwnd = g_blocked_zchange[0];
175            block_behind = g_blocked_zchange[1];
176          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
177    
178          if ((rect.left == blocked.left) && (rect.top == blocked.top)          vchannel_block();
179              && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))  
180            behind = GetNextWindow(hwnd, GW_HWNDPREV);
181            while (behind)
182            {
183                    LONG style;
184    
185                    style = GetWindowLong(behind, GWL_STYLE);
186    
187                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
188                            break;
189    
190                    behind = GetNextWindow(behind, GW_HWNDPREV);
191            }
192    
193            if ((hwnd == block_hwnd) && (behind == block_behind))
194                    vchannel_write("ACK", "%u", serial);
195            else
196            {
197                    int flags = 0;
198                    LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
199                    // handle always on top
200                    if (exstyle & WS_EX_TOPMOST)
201                            flags |= SEAMLESS_CREATE_TOPMOST;
202                    vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, flags);
203            }
204    
205            vchannel_unblock();
206    }
207    
208    static HICON
209    get_icon(HWND hwnd, int large)
210    {
211            HICON icon;
212    
213            if (!SendMessageTimeout(hwnd, WM_GETICON, large ? ICON_BIG : ICON_SMALL,
214                                    0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
215                    return NULL;
216    
217            if (icon)
218                    return icon;
219    
220            /*
221             * Modern versions of Windows uses the voodoo value of 2 instead of 0
222             * for the small icons.
223             */
224            if (!large)
225            {
226                    if (!SendMessageTimeout(hwnd, WM_GETICON, 2,
227                                            0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
228                            return NULL;
229            }
230    
231            if (icon)
232                    return icon;
233    
234            icon = (HICON) GetClassLong(hwnd, large ? GCL_HICON : GCL_HICONSM);
235    
236            if (icon)
237                    return icon;
238    
239            return NULL;
240    }
241    
242    static int
243    extract_icon(HICON icon, char *buffer, int maxlen)
244    {
245            ICONINFO info;
246            HDC hdc;
247            BITMAP mask_bmp, color_bmp;
248            BITMAPINFO bmi;
249            int size, i;
250            char *mask_buf, *color_buf;
251            char *o, *m, *c;
252            int ret = -1;
253    
254            assert(buffer);
255            assert(maxlen > 0);
256    
257            if (!GetIconInfo(icon, &info))
258                    goto fail;
259    
260            if (!GetObject(info.hbmMask, sizeof(BITMAP), &mask_bmp))
261                    goto free_bmps;
262            if (!GetObject(info.hbmColor, sizeof(BITMAP), &color_bmp))
263                    goto free_bmps;
264    
265            if (mask_bmp.bmWidth != color_bmp.bmWidth)
266                    goto free_bmps;
267            if (mask_bmp.bmHeight != color_bmp.bmHeight)
268                    goto free_bmps;
269    
270            if ((mask_bmp.bmWidth * mask_bmp.bmHeight * 4) > maxlen)
271                    goto free_bmps;
272    
273            size = (mask_bmp.bmWidth + 3) / 4 * 4;
274            size *= mask_bmp.bmHeight;
275            size *= 4;
276    
277            mask_buf = malloc(size);
278            if (!mask_buf)
279                    goto free_bmps;
280            color_buf = malloc(size);
281            if (!color_buf)
282                    goto free_mbuf;
283    
284            memset(&bmi, 0, sizeof(BITMAPINFO));
285    
286            bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
287            bmi.bmiHeader.biWidth = mask_bmp.bmWidth;
288            bmi.bmiHeader.biHeight = -mask_bmp.bmHeight;
289            bmi.bmiHeader.biPlanes = 1;
290            bmi.bmiHeader.biBitCount = 32;
291            bmi.bmiHeader.biCompression = BI_RGB;
292            bmi.bmiHeader.biSizeImage = size;
293    
294            hdc = CreateCompatibleDC(NULL);
295            if (!hdc)
296                    goto free_cbuf;
297    
298            if (!GetDIBits(hdc, info.hbmMask, 0, mask_bmp.bmHeight, mask_buf, &bmi, DIB_RGB_COLORS))
299                    goto del_dc;
300            if (!GetDIBits(hdc, info.hbmColor, 0, color_bmp.bmHeight, color_buf, &bmi, DIB_RGB_COLORS))
301                    goto del_dc;
302    
303            o = buffer;
304            m = mask_buf;
305            c = color_buf;
306            for (i = 0; i < size / 4; i++)
307            {
308                    o[0] = c[2];
309                    o[1] = c[1];
310                    o[2] = c[0];
311    
312                    o[3] = ((int) (unsigned char) m[0] + (unsigned char) m[1] +
313                            (unsigned char) m[2]) / 3;
314                    o[3] = 0xff - o[3];
315    
316                    o += 4;
317                    m += 4;
318                    c += 4;
319            }
320    
321            ret = size;
322    
323          del_dc:
324            DeleteDC(hdc);
325    
326          free_cbuf:
327            free(color_buf);
328          free_mbuf:
329            free(mask_buf);
330    
331          free_bmps:
332            DeleteObject(info.hbmMask);
333            DeleteObject(info.hbmColor);
334    
335          fail:
336            return ret;
337    }
338    
339    #define ICON_CHUNK 400
340    
341    static void
342    update_icon(HWND hwnd, HICON icon, int large)
343    {
344            int i, j, size, chunks;
345            char buf[32 * 32 * 4];
346            char asciibuf[ICON_CHUNK * 2 + 1];
347    
348            size = extract_icon(icon, buf, sizeof(buf));
349            if (size <= 0)
350                  return;                  return;
351    
352          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          if ((!large && size != 16 * 16 * 4) || (large && size != 32 * 32 * 4))
353                         hwnd,          {
354                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);                  debug("Unexpected icon size.");
355                    return;
356            }
357    
358            chunks = (size + ICON_CHUNK - 1) / ICON_CHUNK;
359            for (i = 0; i < chunks; i++)
360            {
361                    for (j = 0; j < ICON_CHUNK; j++)
362                    {
363                            if (i * ICON_CHUNK + j >= size)
364                                    break;
365                            sprintf(asciibuf + j * 2, "%02x",
366                                    (int) (unsigned char) buf[i * ICON_CHUNK + j]);
367                    }
368    
369                    vchannel_write("SETICON", "0x%08lx,%d,RGBA,%d,%d,%s", hwnd, i,
370                                   large ? 32 : 16, large ? 32 : 16, asciibuf);
371            }
372  }  }
373    
374  static LRESULT CALLBACK  static LRESULT CALLBACK
375  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
376  {  {
377          HWND hwnd, parent;          HWND hwnd;
378          UINT msg;          UINT msg;
379          WPARAM wparam;          WPARAM wparam;
380          LPARAM lparam;          LPARAM lparam;
# Line 101  wndproc_hook_proc(int code, WPARAM cur_t Line 389  wndproc_hook_proc(int code, WPARAM cur_t
389          wparam = ((CWPSTRUCT *) details)->wParam;          wparam = ((CWPSTRUCT *) details)->wParam;
390          lparam = ((CWPSTRUCT *) details)->lParam;          lparam = ((CWPSTRUCT *) details)->lParam;
391    
392          style = GetWindowLong(hwnd, GWL_STYLE);          if (!is_toplevel(hwnd))
   
         /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,  
            but they exist nonetheless. */  
         if ((style & WS_CHILD) && !(style & WS_POPUP))  
                 goto end;  
   
         if (style & WS_POPUP)  
393          {          {
394                  parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);                  goto end;
                 if (!parent)  
                         parent = (HWND) - 1;  
395          }          }
396          else  
397                  parent = NULL;          style = GetWindowLong(hwnd, GWL_STYLE);
398    
399          switch (msg)          switch (msg)
400          {          {
   
401                  case WM_WINDOWPOSCHANGED:                  case WM_WINDOWPOSCHANGED:
402                          {                          {
403                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;                                  WINDOWPOS *wp = (WINDOWPOS *) lparam;
# Line 128  wndproc_hook_proc(int code, WPARAM cur_t Line 406  wndproc_hook_proc(int code, WPARAM cur_t
406                                  {                                  {
407                                          unsigned short title[150];                                          unsigned short title[150];
408                                          int state;                                          int state;
409                                            DWORD pid;
410                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);                                          int flags;
411                                            HICON icon;
412                                            LONG exstyle;
413    
414                                            exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
415                                            GetWindowThreadProcessId(hwnd, &pid);
416    
417                                            flags = 0;
418                                            if (style & DS_MODALFRAME)
419                                                    flags |= SEAMLESS_CREATE_MODAL;
420                                            // handle always on top
421                                            if (exstyle & WS_EX_TOPMOST)
422                                                    flags |= SEAMLESS_CREATE_TOPMOST;
423    
424                                            vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
425                                                           (long) hwnd, (long) pid,
426                                                           (long) get_parent(hwnd), flags);
427    
428                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
429    
430                                          vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,                                          vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
431                                                         vchannel_strfilter_unicode(title), 0);                                                         vchannel_strfilter_unicode(title), 0);
432    
433                                            icon = get_icon(hwnd, 1);
434                                            if (icon)
435                                            {
436                                                    update_icon(hwnd, icon, 1);
437                                                    DeleteObject(icon);
438                                            }
439    
440                                            icon = get_icon(hwnd, 0);
441                                            if (icon)
442                                            {
443                                                    update_icon(hwnd, icon, 0);
444                                                    DeleteObject(icon);
445                                            }
446    
447                                          if (style & WS_MAXIMIZE)                                          if (style & WS_MAXIMIZE)
448                                                  state = 2;                                                  state = 2;
449                                          else if (style & WS_MINIMIZE)                                          else if (style & WS_MINIMIZE)
# Line 145  wndproc_hook_proc(int code, WPARAM cur_t Line 453  wndproc_hook_proc(int code, WPARAM cur_t
453    
454                                          update_position(hwnd);                                          update_position(hwnd);
455    
456                                          vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);                                          vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
457                                                           state, 0);
458                                  }                                  }
459    
460                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
461                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
462    
463                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
464                                          break;                                          break;
# Line 157  wndproc_hook_proc(int code, WPARAM cur_t Line 466  wndproc_hook_proc(int code, WPARAM cur_t
466                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
467                                          update_position(hwnd);                                          update_position(hwnd);
468    
469                                  if (!(wp->flags & SWP_NOZORDER))                                  break;
470                                  {                          }
                                         vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                        hwnd,  
                                                        wp->flags & SWP_NOACTIVATE ? wp->  
                                                        hwndInsertAfter : 0, 0);  
                                 }  
471    
472                    case WM_SETICON:
473                            if (!(style & WS_VISIBLE))
474                                  break;                                  break;
475    
476                            switch (wparam)
477                            {
478                                    case ICON_BIG:
479                                            if (lparam)
480                                                    update_icon(hwnd, (HICON) lparam, 1);
481                                            else
482                                                    vchannel_write("DELICON", "0x%08lx,RGBA,32,32",
483                                                                   hwnd);
484                                            break;
485                                    case ICON_SMALL:
486                                    case 2:
487                                            if (lparam)
488                                                    update_icon(hwnd, (HICON) lparam, 0);
489                                            else
490                                                    vchannel_write("DELICON", "0x%08lx,RGBA,16,16",
491                                                                   hwnd);
492                                            break;
493                                    default:
494                                            debug("Weird icon size %d", (int) wparam);
495                          }                          }
496    
497                            break;
498    
499                  case WM_SIZE:                  case WM_SIZE:
500                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
501                                  break;                                  break;
# Line 183  wndproc_hook_proc(int code, WPARAM cur_t Line 511  wndproc_hook_proc(int code, WPARAM cur_t
511                  case WM_DESTROY:                  case WM_DESTROY:
512                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE))
513                                  break;                                  break;
514                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
515                          break;                          break;
516    
517                  default:                  default:
# Line 197  wndproc_hook_proc(int code, WPARAM cur_t Line 525  wndproc_hook_proc(int code, WPARAM cur_t
525  static LRESULT CALLBACK  static LRESULT CALLBACK
526  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
527  {  {
528          HWND hwnd, parent;          HWND hwnd;
529          UINT msg;          UINT msg;
530          WPARAM wparam;          WPARAM wparam;
531          LPARAM lparam;          LPARAM lparam;
# Line 212  wndprocret_hook_proc(int code, WPARAM cu Line 540  wndprocret_hook_proc(int code, WPARAM cu
540          wparam = ((CWPRETSTRUCT *) details)->wParam;          wparam = ((CWPRETSTRUCT *) details)->wParam;
541          lparam = ((CWPRETSTRUCT *) details)->lParam;          lparam = ((CWPRETSTRUCT *) details)->lParam;
542    
543          style = GetWindowLong(hwnd, GWL_STYLE);          if (!is_toplevel(hwnd))
544            {
         /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,  
            but they exist nonetheless. */  
         if ((style & WS_CHILD) && !(style & WS_POPUP))  
545                  goto end;                  goto end;
546            }
547    
548            style = GetWindowLong(hwnd, GWL_STYLE);
549    
550          switch (msg)          switch (msg)
551          {          {
552                    case WM_WINDOWPOSCHANGED:
553                            {
554                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
555    
556                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
557                                            break;
558    
559                                    if (!(wp->flags & SWP_NOZORDER))
560                                            update_zorder(hwnd);
561    
562                                    break;
563                            }
564    
565    
566                  case WM_SETTEXT:                  case WM_SETTEXT:
567                          {                          {
568                                  unsigned short title[150];                                  unsigned short title[150];
# Line 229  wndprocret_hook_proc(int code, WPARAM cu Line 571  wndprocret_hook_proc(int code, WPARAM cu
571                                  /* We cannot use the string in lparam because                                  /* We cannot use the string in lparam because
572                                     we need unicode. */                                     we need unicode. */
573                                  GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));                                  GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
574                                  vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,                                  vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
575                                                 vchannel_strfilter_unicode(title), 0);                                                 vchannel_strfilter_unicode(title), 0);
576                                  break;                                  break;
577                          }                          }
578    
579                    case WM_SETICON:
580                            {
581                                    HICON icon;
582    
583                                    /*
584                                     * Somehow, we never get WM_SETICON for the small icon.
585                                     * So trigger a read of it every time the large one is
586                                     * changed.
587                                     */
588                                    icon = get_icon(hwnd, 0);
589                                    if (icon)
590                                    {
591                                            update_icon(hwnd, icon, 0);
592                                            DeleteObject(icon);
593                                    }
594                            }
595    
596                  default:                  default:
597                          break;                          break;
598          }          }
599    
600            if (msg == g_wm_seamless_focus)
601            {
602                    /* For some reason, SetForegroundWindow() on menus
603                       closes them. Ignore focus requests for menu windows. */
604                    if ((GetForegroundWindow() != hwnd) && !is_menu(hwnd))
605                            SetForegroundWindow(hwnd);
606    
607                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
608            }
609    
610        end:        end:
611          return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);          return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
612  }  }
# Line 252  cbt_hook_proc(int code, WPARAM wparam, L Line 621  cbt_hook_proc(int code, WPARAM wparam, L
621          {          {
622                  case HCBT_MINMAX:                  case HCBT_MINMAX:
623                          {                          {
624                                  int show, state;                                  int show, state, blocked;
625                                    HWND hwnd, blocked_hwnd;
626                                    unsigned int serial;
627                                    LONG style;
628    
629                                    WaitForSingleObject(g_mutex, INFINITE);
630                                    blocked_hwnd = g_blocked_state_hwnd;
631                                    serial = g_blocked_state_serial;
632                                    blocked = g_blocked_state;
633                                    ReleaseMutex(g_mutex);
634    
635                                    hwnd = (HWND) wparam;
636    
637                                    style = GetWindowLong(hwnd, GWL_STYLE);
638    
639                                    if (!(style & WS_VISIBLE))
640                                            break;
641    
642                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
643    
# Line 268  cbt_hook_proc(int code, WPARAM wparam, L Line 653  cbt_hook_proc(int code, WPARAM wparam, L
653                                          debug("Unexpected show: %d", show);                                          debug("Unexpected show: %d", show);
654                                          break;                                          break;
655                                  }                                  }
656                                  vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state, 0);  
657                                    if ((blocked_hwnd == hwnd) && (blocked == state))
658                                            vchannel_write("ACK", "%u", serial);
659                                    else
660                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
661                                                           hwnd, state, 0);
662    
663                                  break;                                  break;
664                          }                          }
665    
# Line 308  RemoveHooks(void) Line 699  RemoveHooks(void)
699  }  }
700    
701  DLL_EXPORT void  DLL_EXPORT void
702  SafeMoveWindow(HWND hwnd, int x, int y, int width, int height)  SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
703  {  {
704            RECT rect;
705    
706          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
707            g_block_move_hwnd = hwnd;
708            g_block_move_serial = serial;
709          g_block_move.left = x;          g_block_move.left = x;
710          g_block_move.top = y;          g_block_move.top = y;
711          g_block_move.right = x + width;          g_block_move.right = x + width;
# Line 319  SafeMoveWindow(HWND hwnd, int x, int y, Line 714  SafeMoveWindow(HWND hwnd, int x, int y,
714    
715          SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);          SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
716    
717            vchannel_write("ACK", "%u", serial);
718    
719            if (!GetWindowRect(hwnd, &rect))
720                    debug("GetWindowRect failed!\n");
721            else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
722                     || (rect.bottom != y + height))
723                    update_position(hwnd);
724    
725          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
726            g_block_move_hwnd = NULL;
727          memset(&g_block_move, 0, sizeof(RECT));          memset(&g_block_move, 0, sizeof(RECT));
728          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
729  }  }
730    
731    DLL_EXPORT void
732    SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
733    {
734            WaitForSingleObject(g_mutex, INFINITE);
735            g_blocked_zchange_serial = serial;
736            g_blocked_zchange[0] = hwnd;
737            g_blocked_zchange[1] = behind;
738            ReleaseMutex(g_mutex);
739    
740            if (behind == NULL)
741                    behind = HWND_TOP;
742    
743            SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
744    
745            WaitForSingleObject(g_mutex, INFINITE);
746            g_blocked_zchange[0] = NULL;
747            g_blocked_zchange[1] = NULL;
748            ReleaseMutex(g_mutex);
749    }
750    
751    DLL_EXPORT void
752    SafeFocus(unsigned int serial, HWND hwnd)
753    {
754            WaitForSingleObject(g_mutex, INFINITE);
755            g_blocked_focus_serial = serial;
756            g_blocked_focus = hwnd;
757            ReleaseMutex(g_mutex);
758    
759            SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
760    
761            WaitForSingleObject(g_mutex, INFINITE);
762            g_blocked_focus = NULL;
763            ReleaseMutex(g_mutex);
764    }
765    
766    DLL_EXPORT void
767    SafeSetState(unsigned int serial, HWND hwnd, int state)
768    {
769            LONG style;
770            int curstate;
771    
772            vchannel_block();
773    
774            style = GetWindowLong(hwnd, GWL_STYLE);
775    
776            if (style & WS_MAXIMIZE)
777                    curstate = 2;
778            else if (style & WS_MINIMIZE)
779                    curstate = 1;
780            else
781                    curstate = 0;
782    
783            if (state == curstate)
784            {
785                    vchannel_write("ACK", "%u", serial);
786                    vchannel_unblock();
787                    return;
788            }
789    
790            WaitForSingleObject(g_mutex, INFINITE);
791            g_blocked_state_hwnd = hwnd;
792            g_blocked_state_serial = serial;
793            g_blocked_state = state;
794            ReleaseMutex(g_mutex);
795    
796            vchannel_unblock();
797    
798            if (state == 0)
799                    ShowWindow(hwnd, SW_RESTORE);
800            else if (state == 1)
801                    ShowWindow(hwnd, SW_MINIMIZE);
802            else if (state == 2)
803                    ShowWindow(hwnd, SW_MAXIMIZE);
804            else
805                    debug("Invalid state %d sent.", state);
806    
807            WaitForSingleObject(g_mutex, INFINITE);
808            g_blocked_state_hwnd = NULL;
809            g_blocked_state = -1;
810            ReleaseMutex(g_mutex);
811    }
812    
813  DLL_EXPORT int  DLL_EXPORT int
814  GetInstanceCount()  GetInstanceCount()
815  {  {
# Line 347  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 833  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
833                          ++g_instance_count;                          ++g_instance_count;
834                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);
835    
836                            g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
837    
838                          vchannel_open();                          vchannel_open();
839    
840                          break;                          break;
# Line 358  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 846  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
846                          break;                          break;
847    
848                  case DLL_PROCESS_DETACH:                  case DLL_PROCESS_DETACH:
849                            vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0);
850    
851                          WaitForSingleObject(g_mutex, INFINITE);                          WaitForSingleObject(g_mutex, INFINITE);
852                          --g_instance_count;                          --g_instance_count;
853                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);

Legend:
Removed from v.1145  
changed lines
  Added in v.1449

  ViewVC Help
Powered by ViewVC 1.1.26