1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <gdk/gdkx.h> // gldi_container_present
24
25 #include "applet-struct.h"
26 #include "applet-search.h"
27 #include "applet-listing.h"
28 #include "applet-notifications.h"
29 #include "applet-session.h"
30
31
cd_do_open_session(void)32 void cd_do_open_session (void)
33 {
34 if (cd_do_session_is_running ()) // session already running
35 return;
36
37 // on termine la precedente session.
38 cd_do_exit_session ();
39 cd_do_stop_all_backends (); // on le fait maintenant pour ne pas bloquer au exit.
40
41 // register to draw on dock.
42 if (cd_do_session_is_off ())
43 {
44 gldi_object_register_notification (g_pMainDock,
45 NOTIFICATION_UPDATE,
46 (GldiNotificationFunc) cd_do_update_container,
47 GLDI_RUN_AFTER, NULL);
48 gldi_object_register_notification (g_pMainDock,
49 NOTIFICATION_RENDER,
50 (GldiNotificationFunc) cd_do_render,
51 GLDI_RUN_AFTER, NULL);
52 }
53
54 // wait for keyboard input.
55 gldi_object_register_notification (&myContainerObjectMgr,
56 NOTIFICATION_KEY_PRESSED,
57 (GldiNotificationFunc) cd_do_key_pressed,
58 GLDI_RUN_AFTER, NULL);
59 gldi_object_register_notification (&myWindowObjectMgr,
60 NOTIFICATION_WINDOW_ACTIVATED,
61 (GldiNotificationFunc) cd_do_check_active_dock,
62 GLDI_RUN_AFTER, NULL);
63
64 myData.sCurrentText = g_string_sized_new (20);
65 myConfig.labelDescription.iSize = myConfig.fFontSizeRatio * g_pMainDock->iMaxDockHeight;
66 myData.iPromptAnimationCount = 0;
67 if (myData.pPromptSurface == NULL)
68 {
69 cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (g_pMainDock));
70 myData.pPromptSurface = cairo_dock_create_surface_from_text (D_("Enter your search"), &myConfig.labelDescription, &myData.iPromptWidth, &myData.iPromptHeight);
71 cairo_destroy (pCairoContext);
72 if (g_bUseOpenGL)
73 {
74 myData.iPromptTexture = cairo_dock_create_texture_from_surface (myData.pPromptSurface);
75 }
76 }
77
78 // on montre le main dock.
79 cairo_dock_emit_enter_signal (CAIRO_CONTAINER (g_pMainDock));
80
81 // le main dock prend le focus.
82 gldi_container_present (CAIRO_CONTAINER (g_pMainDock));
83 cairo_dock_freeze_docks (TRUE);
84
85 // On lance l'animation d'attente.
86 cairo_dock_launch_animation (CAIRO_CONTAINER (g_pMainDock));
87
88 myData.iSessionState = 2;
89 }
90
cd_do_close_session(void)91 void cd_do_close_session (void)
92 {
93 if (! cd_do_session_is_running ()) // session not running
94 return;
95
96 // no more keyboard input.
97 gldi_object_remove_notification (&myContainerObjectMgr,
98 NOTIFICATION_KEY_PRESSED,
99 (GldiNotificationFunc) cd_do_key_pressed, NULL);
100 gldi_object_remove_notification (&myWindowObjectMgr,
101 NOTIFICATION_WINDOW_ACTIVATED,
102 (GldiNotificationFunc) cd_do_check_active_dock, NULL);
103
104 g_string_free (myData.sCurrentText, TRUE);
105 myData.sCurrentText = NULL;
106 myData.iNbValidCaracters = 0;
107
108 // on cache les resultats
109 cd_do_hide_listing ();
110
111 g_free (myData.cSearchText);
112 myData.cSearchText = NULL;
113 myData.iCurrentFilter = 0;
114
115 cairo_dock_emit_leave_signal (CAIRO_CONTAINER (g_pMainDock));
116
117 // on quitte dans une animation.
118 myData.iCloseTime = myConfig.iCloseDuration;
119 cairo_dock_launch_animation (CAIRO_CONTAINER (g_pMainDock));
120 cairo_dock_freeze_docks (FALSE);
121
122 myData.iSessionState = 1;
123 }
124
cd_do_exit_session(void)125 void cd_do_exit_session (void)
126 {
127 if (cd_do_session_is_off ()) // session already off
128 return;
129
130
131 cd_do_close_session ();
132
133 myData.iCloseTime = 0;
134
135 gldi_object_remove_notification (g_pMainDock, NOTIFICATION_RENDER, (GldiNotificationFunc) cd_do_render, NULL);
136 gldi_object_remove_notification (g_pMainDock, NOTIFICATION_UPDATE, (GldiNotificationFunc) cd_do_update_container, NULL);
137
138 /// arreter les backends...
139
140
141 if (myData.pCharList != NULL)
142 {
143 cd_do_free_char_list (myData.pCharList);
144 myData.pCharList = NULL;
145 myData.iTextWidth = 0;
146 myData.iTextHeight = 0;
147 cairo_dock_redraw_container (CAIRO_CONTAINER (g_pMainDock));
148 }
149 if (myData.pMatchingIcons != NULL)
150 {
151 Icon *pIcon;
152 GList *ic;
153 for (ic = myData.pMatchingIcons; ic != NULL; ic = ic->next)
154 {
155 pIcon = ic->data;
156 if (pIcon->cDesktopFileName && strncmp (pIcon->cDesktopFileName, "/usr", 4) == 0 && pIcon->image.pSurface != NULL)
157 {
158 cairo_surface_destroy (pIcon->image.pSurface);
159 pIcon->image.pSurface = NULL;
160 if (pIcon->image.iTexture != 0)
161 {
162 _cairo_dock_delete_texture (pIcon->image.iTexture);
163 pIcon->image.iTexture = 0;
164 }
165 }
166 }
167 g_list_free (myData.pMatchingIcons);
168 myData.pMatchingIcons = NULL;
169 myData.pCurrentMatchingElement = NULL;
170 myData.pCurrentMatchingElement = NULL;
171 myData.iMatchingGlideCount = 0;
172 myData.iPreviousMatchingOffset = 0;
173 myData.iCurrentMatchingOffset = 0;
174 }
175
176 myData.iSessionState = 0;
177 }
178
179
180
cd_do_free_char(CDChar * pChar)181 void cd_do_free_char (CDChar *pChar)
182 {
183 if (pChar == NULL)
184 return ;
185 if (pChar->pSurface != NULL)
186 {
187 cairo_surface_destroy (pChar->pSurface);
188 }
189 if (pChar->iTexture != 0)
190 {
191 _cairo_dock_delete_texture (pChar->iTexture);
192 }
193 g_free (pChar);
194 }
195
cd_do_free_char_list(GList * pCharList)196 void cd_do_free_char_list (GList *pCharList)
197 {
198 g_list_foreach (pCharList, (GFunc) cd_do_free_char, NULL);
199 g_list_free (pCharList);
200 }
201
202
cd_do_load_pending_caracters(void)203 void cd_do_load_pending_caracters (void)
204 {
205 cairo_surface_t *pSurface;
206 gboolean bLoadTexture = (CAIRO_CONTAINER_IS_OPENGL (g_pMainDock));
207 gchar c[2] = {'\0', '\0'};
208 CDChar *pChar;
209 cairo_t *pCairoContext = cairo_dock_create_drawing_context_generic (CAIRO_CONTAINER (g_pMainDock));
210 int iDeltaT = cairo_dock_get_animation_delta_t (g_pMainDock);
211 guint i;
212 int iOffsetX=0;
213 for (i = myData.iNbValidCaracters-0; i < myData.sCurrentText->len; i++)
214 {
215 //g_print (" on charge la lettre '%c' (%d) tex:%d\n", myData.sCurrentText->str[i], i, bLoadTexture);
216 c[0] = myData.sCurrentText->str[i];
217
218 pChar = g_new0 (CDChar, 1);
219 pChar->c = c[0];
220 pChar->iInitialX = myData.iTextWidth/2 + iOffsetX; // il part du coin haut droit.
221 pChar->iInitialY = g_pMainDock->container.iHeight/2; // en bas.
222 pChar->iCurrentX = pChar->iInitialX;
223 pChar->iCurrentY = pChar->iInitialY;
224 pChar->fRotationAngle = 10. * myConfig.iAppearanceDuration / iDeltaT;
225 //g_print (" on commence a x=%d\n", pChar->iInitialX);
226 myData.pCharList = g_list_append (myData.pCharList, pChar);
227
228 // on cree la surface.
229 pSurface = cairo_dock_create_surface_from_text (c, &myConfig.labelDescription, &pChar->iWidth, &pChar->iHeight);
230 if (g_pMainDock->container.bIsHorizontal)
231 {
232 myData.iTextWidth += pChar->iWidth;
233 iOffsetX += pChar->iWidth;
234 pChar->iInitialY = g_pMainDock->iMaxDockHeight - pChar->iHeight;
235 myData.iTextHeight = MAX (myData.iTextHeight, pChar->iHeight);
236 }
237 else
238 {
239 myData.iTextHeight += pChar->iHeight;
240 iOffsetX += pChar->iHeight;
241 pChar->iInitialY = g_pMainDock->iMaxDockHeight - pChar->iWidth;
242 myData.iTextWidth = MAX (myData.iTextWidth, pChar->iWidth);
243 }
244
245 // on cree la texture.
246 if (bLoadTexture)
247 {
248 pChar->iTexture = cairo_dock_create_texture_from_surface (pSurface);
249 cairo_surface_destroy (pSurface);
250 }
251 else
252 {
253 pChar->pSurface = pSurface;
254 }
255 }
256 cairo_destroy (pCairoContext);
257 }
258
259
cd_do_compute_final_coords(void)260 void cd_do_compute_final_coords (void)
261 {
262 int x = - myData.iTextWidth / 2; // par rapport au milieu du dock.
263 CDChar *pChar;
264 GList *c;
265 for (c = myData.pCharList; c != NULL; c = c->next)
266 {
267 pChar = c->data;
268
269 pChar->iFinalX = x;
270 pChar->iFinalY = 0;
271 x += pChar->iWidth;
272
273 pChar->iInitialX = pChar->iCurrentX;
274 pChar->iInitialY = pChar->iCurrentY;
275 }
276 }
277
278
cd_do_launch_appearance_animation(void)279 void cd_do_launch_appearance_animation (void)
280 {
281 cd_do_compute_final_coords ();
282 myData.iAppearanceTime = myConfig.iAppearanceDuration;
283 cairo_dock_launch_animation (CAIRO_CONTAINER (g_pMainDock)); // animation de disparition.
284 }
285
286
cd_do_delete_invalid_caracters(void)287 void cd_do_delete_invalid_caracters (void)
288 {
289 if (myData.sCurrentText->len == 0)
290 return;
291
292 // on efface les lettres precedentes jusqu'a la derniere position validee.
293 CDChar *pChar;
294 GList *c = g_list_last (myData.pCharList), *c_prev;
295 guint i;
296 for (i = myData.iNbValidCaracters; i < myData.sCurrentText->len && c != NULL; i ++)
297 {
298 //g_print ("on efface '%c'\n", myData.sCurrentText->str[i]);
299 c_prev = c->prev;
300 pChar = c->data;
301
302 myData.iTextWidth -= pChar->iWidth;
303 cd_do_free_char (pChar);
304 myData.pCharList = g_list_delete_link (myData.pCharList, c); // detruit c.
305 c = c_prev;
306 }
307
308 // on tronque la chaine de la meme maniere.
309 g_string_truncate (myData.sCurrentText, myData.iNbValidCaracters);
310 cd_debug (" -> '%s' (%d)", myData.sCurrentText->str, myData.iNbValidCaracters);
311
312 // on remet a jour la hauteur du texte.
313 myData.iTextHeight = 0;
314 for (c = myData.pCharList; c != NULL; c = c->next)
315 {
316 pChar = c->data;
317 myData.iTextHeight = MAX (myData.iTextHeight, pChar->iHeight);
318 }
319 }
320