/[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 1160 by ossman_, Fri Mar 17 16:23:08 2006 UTC revision 1450 by astrand, Fri Mar 14 07:22:55 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 };  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;  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;  int g_blocked_state SHARED = -1;
62    
63  #pragma data_seg ()  #pragma data_seg ()
# Line 65  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            /* Notepad menus have an owner, but Seamonkey menus does not,
97               so we cannot use the owner in our check. This leaves us with
98               checking WS_EX_TOOLWINDOW and WS_EX_TOPMOST. */
99    
100            LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
101            return (exstyle & (WS_EX_TOOLWINDOW | WS_EX_TOPMOST));
102    }
103    
104    /* Determine the "parent" field for the CREATE response. */
105    static HWND
106    get_parent(HWND hwnd)
107    {
108            HWND result;
109            HWND owner;
110            LONG exstyle;
111    
112            /* Use the same logic to determine if the window should be
113               "transient" (ie have no task icon) as MS uses. This is documented at
114               http://msdn2.microsoft.com/en-us/library/bb776822.aspx */
115            owner = GetWindow(hwnd, GW_OWNER);
116            exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
117            if (!owner && !(exstyle & WS_EX_TOOLWINDOW))
118            {
119                    /* display taskbar icon */
120                    result = NULL;
121            }
122            else
123            {
124                    /* no taskbar icon */
125                    if (owner)
126                            result = owner;
127                    else
128                            result = (HWND) - 1;
129            }
130    
131            return result;
132    }
133    
134  static void  static void
135  update_position(HWND hwnd)  update_position(HWND hwnd)
136  {  {
137          RECT rect, blocked;          RECT rect, blocked;
138            HWND blocked_hwnd;
139            unsigned int serial;
140    
141            WaitForSingleObject(g_mutex, INFINITE);
142            blocked_hwnd = g_block_move_hwnd;
143            serial = g_block_move_serial;
144            memcpy(&blocked, &g_block_move, sizeof(RECT));
145            ReleaseMutex(g_mutex);
146    
147            vchannel_block();
148    
149          if (!GetWindowRect(hwnd, &rect))          if (!GetWindowRect(hwnd, &rect))
150          {          {
151                  debug("GetWindowRect failed!\n");                  debug("GetWindowRect failed!\n");
152                  return;                  goto end;
153          }          }
154    
155            if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
156                && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
157                    goto end;
158    
159            vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
160                           hwnd,
161                           rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
162    
163          end:
164            vchannel_unblock();
165    }
166    
167    static void
168    update_zorder(HWND hwnd)
169    {
170            HWND behind;
171            HWND block_hwnd, block_behind;
172            unsigned int serial;
173    
174          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
175          memcpy(&blocked, &g_block_move, sizeof(RECT));          serial = g_blocked_zchange_serial;
176            block_hwnd = g_blocked_zchange[0];
177            block_behind = g_blocked_zchange[1];
178          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
179    
180          if ((rect.left == blocked.left) && (rect.top == blocked.top)          vchannel_block();
181              && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))  
182            behind = GetNextWindow(hwnd, GW_HWNDPREV);
183            while (behind)
184            {
185                    LONG style;
186    
187                    style = GetWindowLong(behind, GWL_STYLE);
188    
189                    if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
190                            break;
191    
192                    behind = GetNextWindow(behind, GW_HWNDPREV);
193            }
194    
195            if ((hwnd == block_hwnd) && (behind == block_behind))
196                    vchannel_write("ACK", "%u", serial);
197            else
198            {
199                    int flags = 0;
200                    LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
201                    // handle always on top
202                    if (exstyle & WS_EX_TOPMOST)
203                            flags |= SEAMLESS_CREATE_TOPMOST;
204                    vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, flags);
205            }
206    
207            vchannel_unblock();
208    }
209    
210    static HICON
211    get_icon(HWND hwnd, int large)
212    {
213            HICON icon;
214    
215            if (!SendMessageTimeout(hwnd, WM_GETICON, large ? ICON_BIG : ICON_SMALL,
216                                    0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
217                    return NULL;
218    
219            if (icon)
220                    return icon;
221    
222            /*
223             * Modern versions of Windows uses the voodoo value of 2 instead of 0
224             * for the small icons.
225             */
226            if (!large)
227            {
228                    if (!SendMessageTimeout(hwnd, WM_GETICON, 2,
229                                            0, SMTO_ABORTIFHUNG, 1000, (PDWORD_PTR) & icon))
230                            return NULL;
231            }
232    
233            if (icon)
234                    return icon;
235    
236            icon = (HICON) GetClassLong(hwnd, large ? GCL_HICON : GCL_HICONSM);
237    
238            if (icon)
239                    return icon;
240    
241            return NULL;
242    }
243    
244    static int
245    extract_icon(HICON icon, char *buffer, int maxlen)
246    {
247            ICONINFO info;
248            HDC hdc;
249            BITMAP mask_bmp, color_bmp;
250            BITMAPINFO bmi;
251            int size, i;
252            char *mask_buf, *color_buf;
253            char *o, *m, *c;
254            int ret = -1;
255    
256            assert(buffer);
257            assert(maxlen > 0);
258    
259            if (!GetIconInfo(icon, &info))
260                    goto fail;
261    
262            if (!GetObject(info.hbmMask, sizeof(BITMAP), &mask_bmp))
263                    goto free_bmps;
264            if (!GetObject(info.hbmColor, sizeof(BITMAP), &color_bmp))
265                    goto free_bmps;
266    
267            if (mask_bmp.bmWidth != color_bmp.bmWidth)
268                    goto free_bmps;
269            if (mask_bmp.bmHeight != color_bmp.bmHeight)
270                    goto free_bmps;
271    
272            if ((mask_bmp.bmWidth * mask_bmp.bmHeight * 4) > maxlen)
273                    goto free_bmps;
274    
275            size = (mask_bmp.bmWidth + 3) / 4 * 4;
276            size *= mask_bmp.bmHeight;
277            size *= 4;
278    
279            mask_buf = malloc(size);
280            if (!mask_buf)
281                    goto free_bmps;
282            color_buf = malloc(size);
283            if (!color_buf)
284                    goto free_mbuf;
285    
286            memset(&bmi, 0, sizeof(BITMAPINFO));
287    
288            bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
289            bmi.bmiHeader.biWidth = mask_bmp.bmWidth;
290            bmi.bmiHeader.biHeight = -mask_bmp.bmHeight;
291            bmi.bmiHeader.biPlanes = 1;
292            bmi.bmiHeader.biBitCount = 32;
293            bmi.bmiHeader.biCompression = BI_RGB;
294            bmi.bmiHeader.biSizeImage = size;
295    
296            hdc = CreateCompatibleDC(NULL);
297            if (!hdc)
298                    goto free_cbuf;
299    
300            if (!GetDIBits(hdc, info.hbmMask, 0, mask_bmp.bmHeight, mask_buf, &bmi, DIB_RGB_COLORS))
301                    goto del_dc;
302            if (!GetDIBits(hdc, info.hbmColor, 0, color_bmp.bmHeight, color_buf, &bmi, DIB_RGB_COLORS))
303                    goto del_dc;
304    
305            o = buffer;
306            m = mask_buf;
307            c = color_buf;
308            for (i = 0; i < size / 4; i++)
309            {
310                    o[0] = c[2];
311                    o[1] = c[1];
312                    o[2] = c[0];
313    
314                    o[3] = ((int) (unsigned char) m[0] + (unsigned char) m[1] +
315                            (unsigned char) m[2]) / 3;
316                    o[3] = 0xff - o[3];
317    
318                    o += 4;
319                    m += 4;
320                    c += 4;
321            }
322    
323            ret = size;
324    
325          del_dc:
326            DeleteDC(hdc);
327    
328          free_cbuf:
329            free(color_buf);
330          free_mbuf:
331            free(mask_buf);
332    
333          free_bmps:
334            DeleteObject(info.hbmMask);
335            DeleteObject(info.hbmColor);
336    
337          fail:
338            return ret;
339    }
340    
341    #define ICON_CHUNK 400
342    
343    static void
344    update_icon(HWND hwnd, HICON icon, int large)
345    {
346            int i, j, size, chunks;
347            char buf[32 * 32 * 4];
348            char asciibuf[ICON_CHUNK * 2 + 1];
349    
350            size = extract_icon(icon, buf, sizeof(buf));
351            if (size <= 0)
352                  return;                  return;
353    
354          vchannel_write("POSITION,0x%p,%d,%d,%d,%d,0x%x",          if ((!large && size != 16 * 16 * 4) || (large && size != 32 * 32 * 4))
355                         hwnd,          {
356                         rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);                  debug("Unexpected icon size.");
357                    return;
358            }
359    
360            chunks = (size + ICON_CHUNK - 1) / ICON_CHUNK;
361            for (i = 0; i < chunks; i++)
362            {
363                    for (j = 0; j < ICON_CHUNK; j++)
364                    {
365                            if (i * ICON_CHUNK + j >= size)
366                                    break;
367                            sprintf(asciibuf + j * 2, "%02x",
368                                    (int) (unsigned char) buf[i * ICON_CHUNK + j]);
369                    }
370    
371                    vchannel_write("SETICON", "0x%08lx,%d,RGBA,%d,%d,%s", hwnd, i,
372                                   large ? 32 : 16, large ? 32 : 16, asciibuf);
373            }
374  }  }
375    
376  static LRESULT CALLBACK  static LRESULT CALLBACK
377  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
378  {  {
379          HWND hwnd, parent;          HWND hwnd;
380          UINT msg;          UINT msg;
381          WPARAM wparam;          WPARAM wparam;
382          LPARAM lparam;          LPARAM lparam;
# Line 107  wndproc_hook_proc(int code, WPARAM cur_t Line 391  wndproc_hook_proc(int code, WPARAM cur_t
391          wparam = ((CWPSTRUCT *) details)->wParam;          wparam = ((CWPSTRUCT *) details)->wParam;
392          lparam = ((CWPSTRUCT *) details)->lParam;          lparam = ((CWPSTRUCT *) details)->lParam;
393    
394          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)  
395          {          {
396                  parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);                  goto end;
                 if (!parent)  
                         parent = (HWND) - 1;  
397          }          }
398          else  
399                  parent = NULL;          style = GetWindowLong(hwnd, GWL_STYLE);
400    
401          switch (msg)          switch (msg)
402          {          {
# Line 133  wndproc_hook_proc(int code, WPARAM cur_t Line 408  wndproc_hook_proc(int code, WPARAM cur_t
408                                  {                                  {
409                                          unsigned short title[150];                                          unsigned short title[150];
410                                          int state;                                          int state;
411                                            DWORD pid;
412                                          vchannel_write("CREATE,0x%p,0x%p,0x%x", hwnd, parent, 0);                                          int flags;
413                                            HICON icon;
414                                            LONG exstyle;
415    
416                                            exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
417                                            GetWindowThreadProcessId(hwnd, &pid);
418    
419                                            flags = 0;
420                                            if (style & DS_MODALFRAME)
421                                                    flags |= SEAMLESS_CREATE_MODAL;
422                                            // handle always on top
423                                            if (exstyle & WS_EX_TOPMOST)
424                                                    flags |= SEAMLESS_CREATE_TOPMOST;
425    
426                                            vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
427                                                           (long) hwnd, (long) pid,
428                                                           (long) get_parent(hwnd), flags);
429    
430                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));                                          GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
431    
432                                          vchannel_write("TITLE,0x%x,%s,0x%x", hwnd,                                          vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
433                                                         vchannel_strfilter_unicode(title), 0);                                                         vchannel_strfilter_unicode(title), 0);
434    
435                                            icon = get_icon(hwnd, 1);
436                                            if (icon)
437                                            {
438                                                    update_icon(hwnd, icon, 1);
439                                                    DeleteObject(icon);
440                                            }
441    
442                                            icon = get_icon(hwnd, 0);
443                                            if (icon)
444                                            {
445                                                    update_icon(hwnd, icon, 0);
446                                                    DeleteObject(icon);
447                                            }
448    
449                                          if (style & WS_MAXIMIZE)                                          if (style & WS_MAXIMIZE)
450                                                  state = 2;                                                  state = 2;
451                                          else if (style & WS_MINIMIZE)                                          else if (style & WS_MINIMIZE)
# Line 150  wndproc_hook_proc(int code, WPARAM cur_t Line 455  wndproc_hook_proc(int code, WPARAM cur_t
455    
456                                          update_position(hwnd);                                          update_position(hwnd);
457    
458                                          vchannel_write("STATE,0x%p,0x%x,0x%x", hwnd, state, 0);                                          vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
459                                                           state, 0);
460                                  }                                  }
461    
462                                  if (wp->flags & SWP_HIDEWINDOW)                                  if (wp->flags & SWP_HIDEWINDOW)
463                                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
464    
465                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                                  if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
466                                          break;                                          break;
# Line 162  wndproc_hook_proc(int code, WPARAM cur_t Line 468  wndproc_hook_proc(int code, WPARAM cur_t
468                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))                                  if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
469                                          update_position(hwnd);                                          update_position(hwnd);
470    
471                                  if (!(wp->flags & SWP_NOZORDER))                                  break;
472                                  {                          }
                                         HWND block_hwnd, block_behind;  
                                         WaitForSingleObject(g_mutex, INFINITE);  
                                         block_hwnd = g_blocked_zchange[0];  
                                         block_behind = g_blocked_zchange[1];  
                                         ReleaseMutex(g_mutex);  
   
                                         if ((hwnd != block_hwnd)  
                                             || (wp->hwndInsertAfter != block_behind))  
                                         {  
                                                 vchannel_write("ZCHANGE,0x%p,0x%p,0x%x",  
                                                                hwnd,  
                                                                wp->flags & SWP_NOACTIVATE ? wp->  
                                                                hwndInsertAfter : 0, 0);  
                                         }  
                                 }  
473    
474                    case WM_SETICON:
475                            if (!(style & WS_VISIBLE))
476                                  break;                                  break;
477    
478                            switch (wparam)
479                            {
480                                    case ICON_BIG:
481                                            if (lparam)
482                                                    update_icon(hwnd, (HICON) lparam, 1);
483                                            else
484                                                    vchannel_write("DELICON", "0x%08lx,RGBA,32,32",
485                                                                   hwnd);
486                                            break;
487                                    case ICON_SMALL:
488                                    case 2:
489                                            if (lparam)
490                                                    update_icon(hwnd, (HICON) lparam, 0);
491                                            else
492                                                    vchannel_write("DELICON", "0x%08lx,RGBA,16,16",
493                                                                   hwnd);
494                                            break;
495                                    default:
496                                            debug("Weird icon size %d", (int) wparam);
497                          }                          }
498    
499                            break;
500    
501                  case WM_SIZE:                  case WM_SIZE:
502                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))                          if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
503                                  break;                                  break;
# Line 198  wndproc_hook_proc(int code, WPARAM cur_t Line 513  wndproc_hook_proc(int code, WPARAM cur_t
513                  case WM_DESTROY:                  case WM_DESTROY:
514                          if (!(style & WS_VISIBLE))                          if (!(style & WS_VISIBLE))
515                                  break;                                  break;
516                          vchannel_write("DESTROY,0x%p,0x%x", hwnd, 0);                          vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
517                          break;                          break;
518    
519                  default:                  default:
# Line 212  wndproc_hook_proc(int code, WPARAM cur_t Line 527  wndproc_hook_proc(int code, WPARAM cur_t
527  static LRESULT CALLBACK  static LRESULT CALLBACK
528  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)  wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
529  {  {
530          HWND hwnd, parent;          HWND hwnd;
531          UINT msg;          UINT msg;
532          WPARAM wparam;          WPARAM wparam;
533          LPARAM lparam;          LPARAM lparam;
# Line 227  wndprocret_hook_proc(int code, WPARAM cu Line 542  wndprocret_hook_proc(int code, WPARAM cu
542          wparam = ((CWPRETSTRUCT *) details)->wParam;          wparam = ((CWPRETSTRUCT *) details)->wParam;
543          lparam = ((CWPRETSTRUCT *) details)->lParam;          lparam = ((CWPRETSTRUCT *) details)->lParam;
544    
545          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)  
546          {          {
547                  parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);                  goto end;
                 if (!parent)  
                         parent = (HWND) - 1;  
548          }          }
549          else  
550                  parent = NULL;          style = GetWindowLong(hwnd, GWL_STYLE);
551    
552          switch (msg)          switch (msg)
553          {          {
554                    case WM_WINDOWPOSCHANGED:
555                            {
556                                    WINDOWPOS *wp = (WINDOWPOS *) lparam;
557    
558                                    if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
559                                            break;
560    
561                                    if (!(wp->flags & SWP_NOZORDER))
562                                            update_zorder(hwnd);
563    
564                                    break;
565                            }
566    
567    
568                  case WM_SETTEXT:                  case WM_SETTEXT:
569                          {                          {
570                                  unsigned short title[150];                                  unsigned short title[150];
# Line 253  wndprocret_hook_proc(int code, WPARAM cu Line 573  wndprocret_hook_proc(int code, WPARAM cu
573                                  /* We cannot use the string in lparam because                                  /* We cannot use the string in lparam because
574                                     we need unicode. */                                     we need unicode. */
575                                  GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));                                  GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
576                                  vchannel_write("TITLE,0x%p,%s,0x%x", hwnd,                                  vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
577                                                 vchannel_strfilter_unicode(title), 0);                                                 vchannel_strfilter_unicode(title), 0);
578                                  break;                                  break;
579                          }                          }
580    
581                    case WM_SETICON:
582                            {
583                                    HICON icon;
584    
585                                    /*
586                                     * Somehow, we never get WM_SETICON for the small icon.
587                                     * So trigger a read of it every time the large one is
588                                     * changed.
589                                     */
590                                    icon = get_icon(hwnd, 0);
591                                    if (icon)
592                                    {
593                                            update_icon(hwnd, icon, 0);
594                                            DeleteObject(icon);
595                                    }
596                            }
597    
598                  default:                  default:
599                          break;                          break;
600          }          }
601    
602          if (msg == g_wm_seamless_focus)          if (msg == g_wm_seamless_focus)
603          {          {
604                  /* FIXME: SetActiveWindow() kills menus. Need to find a clean                  /* For some reason, SetForegroundWindow() on menus
605                     way to solve this. */                     closes them. Ignore focus requests for menu windows. */
606                  if ((GetActiveWindow() != hwnd) && !parent)                  if ((GetForegroundWindow() != hwnd) && !is_menu(hwnd))
607                          SetActiveWindow(hwnd);                          SetForegroundWindow(hwnd);
608    
609                    vchannel_write("ACK", "%u", g_blocked_focus_serial);
610          }          }
611    
612        end:        end:
# Line 285  cbt_hook_proc(int code, WPARAM wparam, L Line 624  cbt_hook_proc(int code, WPARAM wparam, L
624                  case HCBT_MINMAX:                  case HCBT_MINMAX:
625                          {                          {
626                                  int show, state, blocked;                                  int show, state, blocked;
627                                    HWND hwnd, blocked_hwnd;
628                                    unsigned int serial;
629                                    LONG style;
630    
631                                  WaitForSingleObject(g_mutex, INFINITE);                                  WaitForSingleObject(g_mutex, INFINITE);
632                                    blocked_hwnd = g_blocked_state_hwnd;
633                                    serial = g_blocked_state_serial;
634                                  blocked = g_blocked_state;                                  blocked = g_blocked_state;
635                                  ReleaseMutex(g_mutex);                                  ReleaseMutex(g_mutex);
636    
637                                    hwnd = (HWND) wparam;
638    
639                                    style = GetWindowLong(hwnd, GWL_STYLE);
640    
641                                    if (!(style & WS_VISIBLE))
642                                            break;
643    
644                                  show = LOWORD(lparam);                                  show = LOWORD(lparam);
645    
646                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)                                  if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
# Line 305  cbt_hook_proc(int code, WPARAM wparam, L Line 656  cbt_hook_proc(int code, WPARAM wparam, L
656                                          break;                                          break;
657                                  }                                  }
658    
659                                  if (blocked != state)                                  if ((blocked_hwnd == hwnd) && (blocked == state))
660                                          vchannel_write("STATE,0x%p,0x%x,0x%x", (HWND) wparam, state,                                          vchannel_write("ACK", "%u", serial);
661                                                         0);                                  else
662                                            vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
663                                                           hwnd, state, 0);
664    
665                                  break;                                  break;
666                          }                          }
# Line 348  RemoveHooks(void) Line 701  RemoveHooks(void)
701  }  }
702    
703  DLL_EXPORT void  DLL_EXPORT void
704  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)
705  {  {
706            RECT rect;
707    
708          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
709            g_block_move_hwnd = hwnd;
710            g_block_move_serial = serial;
711          g_block_move.left = x;          g_block_move.left = x;
712          g_block_move.top = y;          g_block_move.top = y;
713          g_block_move.right = x + width;          g_block_move.right = x + width;
# Line 359  SafeMoveWindow(HWND hwnd, int x, int y, Line 716  SafeMoveWindow(HWND hwnd, int x, int y,
716    
717          SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);          SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
718    
719            vchannel_write("ACK", "%u", serial);
720    
721            if (!GetWindowRect(hwnd, &rect))
722                    debug("GetWindowRect failed!\n");
723            else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
724                     || (rect.bottom != y + height))
725                    update_position(hwnd);
726    
727          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
728            g_block_move_hwnd = NULL;
729          memset(&g_block_move, 0, sizeof(RECT));          memset(&g_block_move, 0, sizeof(RECT));
730          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
731  }  }
732    
733  DLL_EXPORT void  DLL_EXPORT void
734  SafeZChange(HWND hwnd, HWND behind)  SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
735  {  {
         if (behind == NULL)  
                 behind = HWND_TOP;  
   
736          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
737            g_blocked_zchange_serial = serial;
738          g_blocked_zchange[0] = hwnd;          g_blocked_zchange[0] = hwnd;
739          g_blocked_zchange[1] = behind;          g_blocked_zchange[1] = behind;
740          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
741    
742            if (behind == NULL)
743                    behind = HWND_TOP;
744    
745          SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);          SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
746    
747          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
# Line 384  SafeZChange(HWND hwnd, HWND behind) Line 751  SafeZChange(HWND hwnd, HWND behind)
751  }  }
752    
753  DLL_EXPORT void  DLL_EXPORT void
754  SafeFocus(HWND hwnd)  SafeFocus(unsigned int serial, HWND hwnd)
755  {  {
756          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
757            g_blocked_focus_serial = serial;
758          g_blocked_focus = hwnd;          g_blocked_focus = hwnd;
759          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
760    
# Line 398  SafeFocus(HWND hwnd) Line 766  SafeFocus(HWND hwnd)
766  }  }
767    
768  DLL_EXPORT void  DLL_EXPORT void
769  SafeSetState(HWND hwnd, int state)  SafeSetState(unsigned int serial, HWND hwnd, int state)
770  {  {
771            LONG style;
772            int curstate;
773    
774            vchannel_block();
775    
776            style = GetWindowLong(hwnd, GWL_STYLE);
777    
778            if (style & WS_MAXIMIZE)
779                    curstate = 2;
780            else if (style & WS_MINIMIZE)
781                    curstate = 1;
782            else
783                    curstate = 0;
784    
785            if (state == curstate)
786            {
787                    vchannel_write("ACK", "%u", serial);
788                    vchannel_unblock();
789                    return;
790            }
791    
792          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
793            g_blocked_state_hwnd = hwnd;
794            g_blocked_state_serial = serial;
795          g_blocked_state = state;          g_blocked_state = state;
796          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
797    
798            vchannel_unblock();
799    
800          if (state == 0)          if (state == 0)
801                  ShowWindow(hwnd, SW_RESTORE);                  ShowWindow(hwnd, SW_RESTORE);
802          else if (state == 1)          else if (state == 1)
# Line 414  SafeSetState(HWND hwnd, int state) Line 807  SafeSetState(HWND hwnd, int state)
807                  debug("Invalid state %d sent.", state);                  debug("Invalid state %d sent.", state);
808    
809          WaitForSingleObject(g_mutex, INFINITE);          WaitForSingleObject(g_mutex, INFINITE);
810            g_blocked_state_hwnd = NULL;
811          g_blocked_state = -1;          g_blocked_state = -1;
812          ReleaseMutex(g_mutex);          ReleaseMutex(g_mutex);
813  }  }
# Line 454  DllMain(HINSTANCE hinstDLL, DWORD ul_rea Line 848  DllMain(HINSTANCE hinstDLL, DWORD ul_rea
848                          break;                          break;
849    
850                  case DLL_PROCESS_DETACH:                  case DLL_PROCESS_DETACH:
851                            vchannel_write("DESTROYGRP", "0x%08lx, 0x%08lx", GetCurrentProcessId(), 0);
852    
853                          WaitForSingleObject(g_mutex, INFINITE);                          WaitForSingleObject(g_mutex, INFINITE);
854                          --g_instance_count;                          --g_instance_count;
855                          ReleaseMutex(g_mutex);                          ReleaseMutex(g_mutex);

Legend:
Removed from v.1160  
changed lines
  Added in v.1450

  ViewVC Help
Powered by ViewVC 1.1.26