wintrayicon.c revision 6747b715
1/*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
27 *
28 * Authors:	Early Ehlinger
29 *		Harold L Hunt II
30 */
31
32#ifdef HAVE_XWIN_CONFIG_H
33#include <xwin-config.h>
34#endif
35#include "win.h"
36#include <shellapi.h>
37#include "winprefs.h"
38
39/*
40 * Initialize the tray icon
41 */
42
43void
44winInitNotifyIcon (winPrivScreenPtr pScreenPriv)
45{
46  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
47  NOTIFYICONDATA	nid = {0};
48
49  nid.cbSize = sizeof (NOTIFYICONDATA);
50  nid.hWnd = pScreenPriv->hwndScreen;
51  nid.uID = pScreenInfo->dwScreen;
52  nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
53  nid.uCallbackMessage = WM_TRAYICON;
54  nid.hIcon = winTaskbarIcon ();
55
56  /* Save handle to the icon so it can be freed later */
57  pScreenPriv->hiconNotifyIcon = nid.hIcon;
58
59  /* Set display and screen-specific tooltip text */
60  snprintf (nid.szTip,
61	    sizeof (nid.szTip),
62	    PROJECT_NAME " Server:%s.%d",
63	    display,
64	    (int) pScreenInfo->dwScreen);
65
66  /* Add the tray icon */
67  if (!Shell_NotifyIcon (NIM_ADD, &nid))
68    ErrorF ("winInitNotifyIcon - Shell_NotifyIcon Failed\n");
69}
70
71
72/*
73 * Delete the tray icon
74 */
75
76void
77winDeleteNotifyIcon (winPrivScreenPtr pScreenPriv)
78{
79  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
80  NOTIFYICONDATA	nid = {0};
81
82#if 0
83  ErrorF ("winDeleteNotifyIcon\n");
84#endif
85
86  nid.cbSize = sizeof (NOTIFYICONDATA);
87  nid.hWnd = pScreenPriv->hwndScreen;
88  nid.uID = pScreenInfo->dwScreen;
89
90  /* Delete the tray icon */
91  if (!Shell_NotifyIcon (NIM_DELETE, &nid))
92    {
93      ErrorF ("winDeleteNotifyIcon - Shell_NotifyIcon failed\n");
94      return;
95    }
96
97  /* Free the icon that was loaded */
98  if (pScreenPriv->hiconNotifyIcon != NULL
99      && DestroyIcon (pScreenPriv->hiconNotifyIcon) == 0)
100    {
101      ErrorF ("winDeleteNotifyIcon - DestroyIcon failed\n");
102    }
103  pScreenPriv->hiconNotifyIcon = NULL;
104}
105
106
107/*
108 * Process messages intended for the tray icon
109 */
110
111LRESULT
112winHandleIconMessage (HWND hwnd, UINT message,
113		      WPARAM wParam, LPARAM lParam,
114		      winPrivScreenPtr pScreenPriv)
115{
116#if defined(XWIN_MULTIWINDOWEXTWM) || defined(XWIN_MULTIWINDOW)
117  winScreenInfo		*pScreenInfo = pScreenPriv->pScreenInfo;
118#endif
119
120  switch (lParam)
121    {
122    case WM_LBUTTONUP:
123      /* Restack and bring all windows to top */
124      SetForegroundWindow (hwnd);
125
126#ifdef XWIN_MULTIWINDOWEXTWM
127      if (pScreenInfo->fMWExtWM)
128	winMWExtWMRestackWindows (pScreenInfo->pScreen);
129#endif
130      break;
131
132    case WM_LBUTTONDBLCLK:
133      /* Display Exit dialog box */
134      winDisplayExitDialog (pScreenPriv);
135      break;
136
137    case WM_RBUTTONUP:
138      {
139	POINT		ptCursor;
140	HMENU		hmenuPopup;
141	HMENU		hmenuTray;
142
143	/* Get cursor position */
144	GetCursorPos (&ptCursor);
145
146	/* Load tray icon menu resource */
147	hmenuPopup = LoadMenu (g_hInstance,
148			       MAKEINTRESOURCE(IDM_TRAYICON_MENU));
149	if (!hmenuPopup)
150	  ErrorF ("winHandleIconMessage - LoadMenu failed\n");
151
152	/* Get actual tray icon menu */
153	hmenuTray = GetSubMenu (hmenuPopup, 0);
154
155#ifdef XWIN_MULTIWINDOW
156	/* Check for MultiWindow mode */
157	if (pScreenInfo->fMultiWindow)
158	  {
159	    MENUITEMINFO		mii = {0};
160
161	    /* Root is shown, remove the check box */
162
163	    /* Setup menu item info structure */
164	    mii.cbSize = sizeof (MENUITEMINFO);
165	    mii.fMask = MIIM_STATE;
166	    mii.fState = MFS_CHECKED;
167
168	    /* Unheck box if root is shown */
169	    if (pScreenPriv->fRootWindowShown)
170	      mii.fState = MFS_UNCHECKED;
171
172	    /* Set menu state */
173	    SetMenuItemInfo (hmenuTray, ID_APP_HIDE_ROOT, FALSE, &mii);
174	  }
175	else
176#endif
177	  {
178	    /* Remove Hide Root Window button */
179	    RemoveMenu (hmenuTray,
180			ID_APP_HIDE_ROOT,
181			MF_BYCOMMAND);
182	  }
183
184	SetupRootMenu ((unsigned long)hmenuTray);
185
186	/*
187	 * NOTE: This three-step procedure is required for
188	 * proper popup menu operation.  Without the
189	 * call to SetForegroundWindow the
190	 * popup menu will often not disappear when you click
191	 * outside of it.  Without the PostMessage the second
192	 * time you display the popup menu it might immediately
193	 * disappear.
194	 */
195	SetForegroundWindow (hwnd);
196	TrackPopupMenuEx (hmenuTray,
197			  TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RIGHTBUTTON,
198			  ptCursor.x, ptCursor.y,
199			  hwnd,
200			  NULL);
201	PostMessage (hwnd, WM_NULL, 0, 0);
202
203	/* Free menu */
204	DestroyMenu (hmenuPopup);
205      }
206      break;
207    }
208
209  return 0;
210}
211