view plugins/docklet/MinimizeToTray.c @ 12498:a2de852981c1

[gaim-migrate @ 14810] SF Patch #1380806 from charkins "leave docklet loaded when notification area is not present" "From the summary, this sounds weird, but I think its better behavior. This really only effects some odd corner cases. The existing behavior is that the docklet plugin unloads itself after 10 seconds if the tray icon isn't created. The behavior with this patch is that there is a 3 second timeout (this is necessary to avoid race condition when restoring the gtkblist's visibility state on startup). After this timeout, the docklet plugin stays loaded waiting for a notification to appear, but is essentially non-functional. In the typical scenario, this patch doesn't effect the behavior. Here are some examples of where it does matter: 1) If gaim is closed with the buddy list hidden to the docklet, then gaim is started again without a notification area, the buddy list doesn't show up for 10 seconds (the time it takes for the docklet to timeout). This patch would reduce this to 3 seconds. 2) If the user removes the notification area from their panel, maybe to remove it from one panel and add it to a different panel, but doesn't add a new one back within 10 seconds, the current behavior would cause the docklet plugin to be unloaded. With this patch, the tray icon would automatically be added to the new notification area when it becomes available. 3) The gnome-panel dies and is not restarted within 10 seconds. Similar to #2. (There was a bug filed for this, but can't find it right now). My main concern was that it could be confusing to the user if they enable the docklet plugin, then 10 seconds later it gets disabled without any notification. This patch doesn't add any notification, but leaves the plugin running so it will automatically use a notification area when one becomes available. I also removed an unused parameter from docklet_remove() and changed the plugin description slightly to reflect the change in queuing/notification. Not sure how clear this is, so bug me on #gaim if you have any questions. --charkins" I made a few changes to this patch, but nothing terribly significant... committer: Tailor Script <tailor@pidgin.im>
author Richard Laager <rlaager@wiktel.com>
date Fri, 16 Dec 2005 09:16:14 +0000
parents 9beb663a6fb5
children 6de39a8cc2c1
line wrap: on
line source

/* MinimizeToTray
 *
 * A couple of routines to show how to make it produce a custom caption
 * animation to make it look like we are minimizing to and maximizing 
 * from the system tray
 *
 * These routines are public domain, but it would be nice if you dropped
 * me a line if you use them!
 *
 * 1.0 29.06.2000 Initial version
 * 1.1 01.07.2000 The window retains it's place in the Z-order of windows
 *     when minimized/hidden. This means that when restored/shown, it doesn't
 *     always appear as the foreground window unless we call SetForegroundWindow
 *
 * Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
 */
#include <windows.h>

#ifndef IDANI_OPEN
#define IDANI_OPEN 1
#endif
#ifndef IDANI_CLOSE
#define IDANI_CLOSE 2
#endif
#ifndef IDANI_CAPTION
#define IDANI_CAPTION 3
#endif

#define DEFAULT_RECT_WIDTH 150
#define DEFAULT_RECT_HEIGHT 30

static void GetTrayWndRect(LPRECT lpTrayRect)
{
  APPBARDATA appBarData;
  HWND hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);

  if(hShellTrayWnd)
  {
    HWND hTrayNotifyWnd=FindWindowEx(hShellTrayWnd,NULL,TEXT("TrayNotifyWnd"),NULL);
    if(hTrayNotifyWnd)
    {
      GetWindowRect(hTrayNotifyWnd,lpTrayRect);
      return;
    }
  }

  appBarData.cbSize=sizeof(appBarData);
  if(SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData))
  {
    switch(appBarData.uEdge)
    {
      case ABE_LEFT:
      case ABE_RIGHT:
	lpTrayRect->top=appBarData.rc.bottom-100;
	lpTrayRect->bottom=appBarData.rc.bottom-16;
	lpTrayRect->left=appBarData.rc.left;
	lpTrayRect->right=appBarData.rc.right;
	break;

      case ABE_TOP:
      case ABE_BOTTOM:
	lpTrayRect->top=appBarData.rc.top;
	lpTrayRect->bottom=appBarData.rc.bottom;
	lpTrayRect->left=appBarData.rc.right-100;
	lpTrayRect->right=appBarData.rc.right-16;
	break;
    }

    return;
  }

  hShellTrayWnd=FindWindowEx(NULL,NULL,TEXT("Shell_TrayWnd"),NULL);
  if(hShellTrayWnd)
  {
    GetWindowRect(hShellTrayWnd,lpTrayRect);
    if(lpTrayRect->right-lpTrayRect->left>DEFAULT_RECT_WIDTH)
      lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
    if(lpTrayRect->bottom-lpTrayRect->top>DEFAULT_RECT_HEIGHT)
      lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;

    return;
  }

  SystemParametersInfo(SPI_GETWORKAREA,0,lpTrayRect,0);
  lpTrayRect->left=lpTrayRect->right-DEFAULT_RECT_WIDTH;
  lpTrayRect->top=lpTrayRect->bottom-DEFAULT_RECT_HEIGHT;
}

static int GetDoAnimateMinimize(void)
{
  ANIMATIONINFO ai;

  ai.cbSize=sizeof(ai);
  SystemParametersInfo(SPI_GETANIMATION,sizeof(ai),&ai,0);

  return ai.iMinAnimate?TRUE:FALSE;
}

void MinimizeWndToTray(HWND hWnd)
{
  if(!IsWindowVisible(hWnd)) 
    return;
  if(GetDoAnimateMinimize())
  {
    RECT rcFrom,rcTo;

    GetWindowRect(hWnd,&rcFrom);
    GetTrayWndRect(&rcTo);

    DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  }

  ShowWindow(hWnd,SW_HIDE);
}

void RestoreWndFromTray(HWND hWnd)
{
  if(IsWindowVisible(hWnd)) 
    return;
  if(GetDoAnimateMinimize())
  {
    RECT rcFrom,rcTo;
    GetTrayWndRect(&rcFrom);
    GetWindowRect(hWnd,&rcTo);

    DrawAnimatedRects(hWnd,IDANI_CAPTION,&rcFrom,&rcTo);
  }

  ShowWindow(hWnd,SW_SHOW);
  SetActiveWindow(hWnd);
  SetForegroundWindow(hWnd);
}