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 <math.h>
21 #include <GL/gl.h>
22 #include <GL/glu.h>
23
24 #include "cairo-dock-separator-manager.h" // gldi_auto_separator_icon_new
25 #include "cairo-dock-log.h"
26 #include "cairo-dock-draw-opengl.h" // for the redirected texture
27 #include "cairo-dock-data-renderer.h" // cairo_dock_reload_data_renderer_on_icon/cairo_dock_refresh_data_renderer
28 #include "cairo-dock-windows-manager.h" // gldi_windows_get_active
29 #include "cairo-dock-indicator-manager.h" // myIndicators.bUseClassIndic
30 #include "cairo-dock-draw.h"
31 #include "cairo-dock-animations.h"
32 #include "cairo-dock-image-buffer.h"
33 #include "cairo-dock-module-manager.h" // CAIRO_DOCK_MODULE_CAN_DESKLET
34 #include "cairo-dock-module-instance-manager.h" // pModuleInstance->
35 #include "cairo-dock-icon-factory.h"
36 #include "cairo-dock-icon-facility.h"
37 #include "cairo-dock-applications-manager.h" // myTaskbarParam.bHideVisibleApplis
38 #include "cairo-dock-stack-icon-manager.h"
39 #include "cairo-dock-separator-manager.h"
40 #include "cairo-dock-class-icon-manager.h"
41 #include "cairo-dock-application-facility.h"
42 #include "cairo-dock-launcher-manager.h"
43 #include "cairo-dock-config.h" // cairo_dock_is_loading
44 #include "cairo-dock-dock-facility.h"
45 #include "cairo-dock-log.h"
46 #include "cairo-dock-menu.h" // gldi_menu_popup
47 #include "cairo-dock-dock-manager.h"
48 #include "cairo-dock-dock-visibility.h" // gldi_dock_search_overlapping_window
49 #include "cairo-dock-flying-container.h"
50 #include "cairo-dock-backends-manager.h"
51 #include "cairo-dock-class-manager.h" // cairo_dock_check_class_subdock_is_empty
52 #include "cairo-dock-desktop-manager.h"
53 #include "cairo-dock-windows-manager.h" // gldi_windows_get_active
54 #include "cairo-dock-dock-factory.h"
55
56 // dependencies
57 extern CairoDockHidingEffect *g_pHidingBackend;
58 extern CairoDockHidingEffect *g_pKeepingBelowBackend;
59 extern gboolean g_bUseOpenGL;
60 extern CairoDockGLConfig g_openglConfig;
61
62 // private
63 static Icon *s_pIconClicked = NULL; // pour savoir quand on deplace une icone a la souris. Dangereux si l'icone se fait effacer en cours ...
64 static int s_iClickX, s_iClickY; // coordonnees du clic dans le dock, pour pouvoir initialiser le deplacement apres un seuil.
65 static int s_iSidShowSubDockDemand = 0;
66 static int s_iSidActionOnDragHover = 0;
67 static CairoDock *s_pDockShowingSubDock = NULL; // on n'accede pas a son contenu, seulement l'adresse.
68 static CairoDock *s_pSubDockShowing = NULL; // on n'accede pas a son contenu, seulement l'adresse.
69 static CairoFlyingContainer *s_pFlyingContainer = NULL;
70 static int s_iFirstClickX=0, s_iFirstClickY=0; // for double-click.
71 static gboolean s_bFrozenDock = FALSE;
72 static gboolean s_bIconDragged = FALSE;
73 static gboolean _check_mouse_outside (CairoDock *pDock);
74 static void cairo_dock_stop_icon_glide (CairoDock *pDock);
75 #define CD_CLICK_ZONE 5
76
77 /////////////////
78 /// CALLBACKS ///
79 /////////////////
80
_mouse_is_really_outside(CairoDock * pDock)81 static gboolean _mouse_is_really_outside (CairoDock *pDock)
82 {
83 int x1, x2, y1, y2;
84 if (pDock->iInputState == CAIRO_DOCK_INPUT_ACTIVE)
85 {
86 x1 = (pDock->container.iWidth - pDock->iActiveWidth) * pDock->fAlign;
87 x2 = x1 + pDock->iActiveWidth;
88 if (pDock->container.bDirectionUp)
89 {
90 y1 = pDock->container.iHeight - pDock->iActiveHeight + 1;
91 y2 = pDock->container.iHeight;
92 }
93 else
94 {
95 y1 = 0;
96 y2 = pDock->iActiveHeight - 1;
97 }
98 }
99 else if (pDock->iInputState == CAIRO_DOCK_INPUT_AT_REST)
100 {
101 x1 = (pDock->container.iWidth - pDock->iMinDockWidth) * pDock->fAlign;
102 x2 = x1 + pDock->iMinDockWidth;
103 if (pDock->container.bDirectionUp)
104 {
105 y1 = pDock->container.iHeight - pDock->iMinDockHeight + 1;
106 y2 = pDock->container.iHeight;
107 }
108 else
109 {
110 y1 = 0;
111 y2 = pDock->iMinDockHeight - 1;
112 }
113 }
114 else // hidden
115 return TRUE;
116 if (pDock->container.iMouseX <= x1
117 || pDock->container.iMouseX >= x2)
118 return TRUE;
119 if (pDock->container.iMouseY < y1
120 || pDock->container.iMouseY > y2) // Note: Compiz has a bug: when using the "cube rotation" plug-in, it will reserve 2 pixels for itself on the left and right edges of the screen. So the mouse is not inside the dock when it's at x=0 or x=Ws-1 (no 'enter' event is sent; it's as if the x=0 or x=Ws-1 vertical line of pixels is out of the screen).
121 return TRUE;
122
123 return FALSE;
124 }
125
cairo_dock_freeze_docks(gboolean bFreeze)126 void cairo_dock_freeze_docks (gboolean bFreeze)
127 {
128 s_bFrozenDock = bFreeze; /// instead, try to connect to the motion-event and intercept it ...
129 }
130
_on_expose(G_GNUC_UNUSED GtkWidget * pWidget,cairo_t * pCairoContext,CairoDock * pDock)131 static gboolean _on_expose (G_GNUC_UNUSED GtkWidget *pWidget, cairo_t *pCairoContext, CairoDock *pDock)
132 {
133 if (g_bUseOpenGL && pDock->pRenderer->render_opengl != NULL) // OpenGL rendering
134 {
135 GdkRectangle area;
136 double x1, x2, y1, y2;
137 cairo_clip_extents (pCairoContext, &x1, &y1, &x2, &y2);
138 area.x = x1;
139 area.y = y1;
140 area.width = x2 - x1;
141 area.height = y2 - y1;
142
143 if (! gldi_gl_container_begin_draw_full (CAIRO_CONTAINER (pDock), area.x + area.y != 0 ? &area : NULL, TRUE))
144 return FALSE;
145
146 if (cairo_dock_is_loading ())
147 {
148 // don't draw anything, just let it transparent
149 }
150 else if (cairo_dock_is_hidden (pDock) && (g_pHidingBackend == NULL || !g_pHidingBackend->bCanDisplayHiddenDock))
151 {
152 cairo_dock_render_hidden_dock_opengl (pDock);
153 }
154 else
155 {
156 gldi_object_notify (pDock, NOTIFICATION_RENDER, pDock, NULL);
157 }
158
159 gldi_gl_container_end_draw (CAIRO_CONTAINER (pDock));
160 }
161 else if (! g_bUseOpenGL && pDock->pRenderer->render != NULL) // cairo rendering
162 {
163 cairo_dock_init_drawing_context_on_container (CAIRO_CONTAINER (pDock), pCairoContext);
164
165 if (cairo_dock_is_loading ())
166 {
167 // don't draw anything, just let it transparent
168 }
169 else if (cairo_dock_is_hidden (pDock) && (g_pHidingBackend == NULL || !g_pHidingBackend->bCanDisplayHiddenDock))
170 {
171 cairo_dock_render_hidden_dock (pCairoContext, pDock);
172 }
173 else
174 {
175 gldi_object_notify (pDock, NOTIFICATION_RENDER, pDock, pCairoContext);
176 }
177 }
178 return FALSE;
179 }
180
181
_emit_leave_signal_delayed(CairoDock * pDock)182 static gboolean _emit_leave_signal_delayed (CairoDock *pDock)
183 {
184 //g_print ("%s(%d)\n", __func__, pDock->iRefCount);
185 cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));
186 pDock->iSidLeaveDemand = 0;
187 return FALSE;
188 }
_cairo_dock_show_sub_dock_delayed(CairoDock * pDock)189 static gboolean _cairo_dock_show_sub_dock_delayed (CairoDock *pDock)
190 {
191 s_iSidShowSubDockDemand = 0;
192 s_pDockShowingSubDock = NULL;
193 s_pSubDockShowing = NULL;
194 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons);
195 //g_print ("%s (%x, %x)", __func__, icon, icon ? icon->pSubDock:0);
196 if (icon != NULL && icon->pSubDock != NULL)
197 cairo_dock_show_subdock (icon, pDock);
198
199 return FALSE;
200 }
_search_icon(Icon * icon,gpointer * data)201 static void _search_icon (Icon *icon, gpointer *data)
202 {
203 if (icon == data[0])
204 data[1] = icon;
205 }
_cairo_dock_action_on_drag_hover(Icon * pIcon)206 static gboolean _cairo_dock_action_on_drag_hover (Icon *pIcon)
207 {
208 gpointer data[2] = {pIcon, NULL};
209 gldi_icons_foreach_in_docks ((GldiIconFunc)_search_icon, data); // on verifie que l'icone ne s'est pas faite effacee entre-temps.
210 pIcon = data[1];
211 if (pIcon && pIcon->iface.action_on_drag_hover)
212 pIcon->iface.action_on_drag_hover (pIcon);
213 s_iSidActionOnDragHover = 0;
214 return FALSE;
215 }
_on_change_icon(Icon * pLastPointedIcon,Icon * pPointedIcon,CairoDock * pDock)216 static void _on_change_icon (Icon *pLastPointedIcon, Icon *pPointedIcon, CairoDock *pDock)
217 {
218 //g_print ("%s (%s -> %s)\n", __func__, pLastPointedIcon?pLastPointedIcon->cName:"none", pPointedIcon?pPointedIcon->cName:"none");
219 //cd_debug ("on change d'icone dans %x (-> %s)", pDock, (pPointedIcon != NULL ? pPointedIcon->cName : "rien"));
220 if (s_iSidShowSubDockDemand != 0 && pDock == s_pDockShowingSubDock)
221 {
222 //cd_debug ("on annule la demande de montrage de sous-dock");
223 g_source_remove (s_iSidShowSubDockDemand);
224 s_iSidShowSubDockDemand = 0;
225 s_pDockShowingSubDock = NULL;
226 s_pSubDockShowing = NULL;
227 }
228
229 // take action when dragging something onto an icon
230 if (s_iSidActionOnDragHover != 0)
231 {
232 //cd_debug ("on annule la demande de montrage d'appli");
233 g_source_remove (s_iSidActionOnDragHover);
234 s_iSidActionOnDragHover = 0;
235 }
236
237 if (pDock->bIsDragging && pPointedIcon && pPointedIcon->iface.action_on_drag_hover)
238 {
239 s_iSidActionOnDragHover = g_timeout_add (600, (GSourceFunc) _cairo_dock_action_on_drag_hover, pPointedIcon);
240 }
241
242 // replace dialogs
243 gldi_dialogs_refresh_all ();
244
245 // hide the sub-dock of the previous pointed icon
246 if (pLastPointedIcon != NULL && pLastPointedIcon->pSubDock != NULL) // on a quitte une icone ayant un sous-dock.
247 {
248 CairoDock *pSubDock = pLastPointedIcon->pSubDock;
249 if (gldi_container_is_visible (CAIRO_CONTAINER (pSubDock))) // le sous-dock est visible, on retarde son cachage.
250 {
251 //g_print ("on cache %s en changeant d'icone\n", pLastPointedIcon->cName);
252 if (pSubDock->iSidLeaveDemand == 0)
253 {
254 //g_print (" on retarde le cachage du dock de %dms\n", MAX (myDocksParam.iLeaveSubDockDelay, 300));
255 pSubDock->iSidLeaveDemand = g_timeout_add (MAX (myDocksParam.iLeaveSubDockDelay, 300), (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pSubDock); // on force le retard meme si iLeaveSubDockDelay est a 0, car lorsqu'on entre dans un sous-dock, il arrive frequemment qu'on glisse hors de l'icone qui pointe dessus, et c'est tres desagreable d'avoir le dock qui se ferme avant d'avoir pu entre dedans.
256 }
257 }
258 }
259
260 // show the sub-dock of the current pointed icon
261 if (pPointedIcon != NULL && pPointedIcon->pSubDock != NULL && (! myDocksParam.bShowSubDockOnClick || CAIRO_DOCK_IS_APPLI (pPointedIcon) || pDock->bIsDragging)) // on entre sur une icone ayant un sous-dock.
262 {
263 // if we were leaving the sub-dock, cancel that.
264 if (pPointedIcon->pSubDock->iSidLeaveDemand != 0)
265 {
266 g_source_remove (pPointedIcon->pSubDock->iSidLeaveDemand);
267 pPointedIcon->pSubDock->iSidLeaveDemand = 0;
268 }
269 // and show the sub-dock, possibly with a delay.
270 if (myDocksParam.iShowSubDockDelay > 0)
271 {
272 if (s_iSidShowSubDockDemand != 0)
273 g_source_remove (s_iSidShowSubDockDemand);
274 s_iSidShowSubDockDemand = g_timeout_add (myDocksParam.iShowSubDockDelay, (GSourceFunc) _cairo_dock_show_sub_dock_delayed, pDock); // we can't be showing more than 1 sub-dock, so this timeout can be global to all docks.
275 s_pDockShowingSubDock = pDock;
276 s_pSubDockShowing = pPointedIcon->pSubDock;
277 }
278 else
279 cairo_dock_show_subdock (pPointedIcon, pDock);
280 }
281
282 // notify everybody
283 if (pPointedIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pPointedIcon))
284 {
285 gboolean bStartAnimation = FALSE;
286 gldi_object_notify (pDock, NOTIFICATION_ENTER_ICON, pPointedIcon, pDock, &bStartAnimation);
287
288 if (bStartAnimation)
289 {
290 cairo_dock_mark_icon_as_hovered_by_mouse (pPointedIcon); // mark the animation as 'hover' if it's not already in another state (clicked, etc).
291 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
292 }
293 }
294 }
295
296
cairo_dock_stop_icon_glide(CairoDock * pDock)297 static void cairo_dock_stop_icon_glide (CairoDock *pDock)
298 {
299 Icon *icon;
300 GList *ic;
301 for (ic = pDock->icons; ic != NULL; ic = ic->next)
302 {
303 icon = ic->data;
304 icon->fGlideOffset = 0;
305 icon->iGlideDirection = 0;
306 }
307 }
_cairo_dock_make_icon_glide(Icon * pPointedIcon,Icon * pMovingicon,CairoDock * pDock)308 static void _cairo_dock_make_icon_glide (Icon *pPointedIcon, Icon *pMovingicon, CairoDock *pDock)
309 {
310 Icon *icon;
311 GList *ic;
312 for (ic = pDock->icons; ic != NULL; ic = ic->next)
313 {
314 icon = ic->data;
315 if (icon == pMovingicon)
316 continue;
317 //if (pDock->container.iMouseX > s_pMovingicon->fDrawXAtRest + s_pMovingicon->fWidth * s_pMovingicon->fScale /2) // on a deplace l'icone a droite. // fDrawXAtRest
318 if (pMovingicon->fXAtRest < pPointedIcon->fXAtRest) // on a deplace l'icone a droite.
319 {
320 //g_print ("%s : %.2f / %.2f ; %.2f / %d (%.2f)\n", icon->cName, icon->fXAtRest, pMovingicon->fXAtRest, icon->fDrawX, pDock->container.iMouseX, icon->fGlideOffset);
321 if (icon->fXAtRest > pMovingicon->fXAtRest && icon->fDrawX < pDock->container.iMouseX + 5 && icon->fGlideOffset == 0) // icone entre l'icone deplacee et le curseur.
322 {
323 //g_print (" %s glisse vers la gauche\n", icon->cName);
324 icon->iGlideDirection = -1;
325 }
326 else if (icon->fXAtRest > pMovingicon->fXAtRest && icon->fDrawX > pDock->container.iMouseX && icon->fGlideOffset != 0)
327 {
328 //g_print (" %s glisse vers la droite\n", icon->cName);
329 icon->iGlideDirection = 1;
330 }
331 else if (icon->fXAtRest < pMovingicon->fXAtRest && icon->fGlideOffset > 0)
332 {
333 //g_print (" %s glisse en sens inverse vers la gauche\n", icon->cName);
334 icon->iGlideDirection = -1;
335 }
336 }
337 else
338 {
339 //g_print ("deplacement de %s vers la gauche (%.2f / %d)\n", icon->cName, icon->fDrawX + icon->fWidth * fMaxScale + myIconsParam.iIconGap, pDock->container.iMouseX);
340 if (icon->fXAtRest < pMovingicon->fXAtRest && icon->fDrawX + icon->image.iWidth + myIconsParam.iIconGap >= pDock->container.iMouseX && icon->fGlideOffset == 0) // icone entre l'icone deplacee et le curseur.
341 {
342 //g_print (" %s glisse vers la droite\n", icon->cName);
343 icon->iGlideDirection = 1;
344 }
345 else if (icon->fXAtRest < pMovingicon->fXAtRest && icon->fDrawX + icon->image.iWidth + myIconsParam.iIconGap <= pDock->container.iMouseX && icon->fGlideOffset != 0)
346 {
347 //g_print (" %s glisse vers la gauche\n", icon->cName);
348 icon->iGlideDirection = -1;
349 }
350 else if (icon->fXAtRest > pMovingicon->fXAtRest && icon->fGlideOffset < 0)
351 {
352 //g_print (" %s glisse en sens inverse vers la droite\n", icon->cName);
353 icon->iGlideDirection = 1;
354 }
355 }
356 }
357 }
_on_motion_notify(GtkWidget * pWidget,GdkEventMotion * pMotion,CairoDock * pDock)358 static gboolean _on_motion_notify (GtkWidget* pWidget,
359 GdkEventMotion* pMotion,
360 CairoDock *pDock)
361 {
362 static double fLastTime = 0;
363 if (s_bFrozenDock && pMotion != NULL && pMotion->time != 0)
364 return FALSE;
365 Icon *pPointedIcon=NULL, *pLastPointedIcon = cairo_dock_get_pointed_icon (pDock->icons);
366 //g_print ("%s (%.2f;%.2f, %d)\n", __func__, pMotion->x, pMotion->y, pDock->iInputState);
367
368 if (pMotion != NULL)
369 {
370 //g_print ("%s (%d,%d) (%d, %.2fms, bAtBottom:%d; bIsShrinkingDown:%d)\n", __func__, (int) pMotion->x, (int) pMotion->y, pMotion->is_hint, pMotion->time - fLastTime, pDock->bAtBottom, pDock->bIsShrinkingDown);
371 //\_______________ On deplace le dock si ALT est enfoncee.
372 if ((pMotion->state & GDK_MOD1_MASK) && (pMotion->state & GDK_BUTTON1_MASK))
373 {
374 if (pDock->container.bIsHorizontal)
375 {
376 pDock->container.iWindowPositionX = pMotion->x_root - pDock->container.iMouseX;
377 pDock->container.iWindowPositionY = pMotion->y_root - pDock->container.iMouseY;
378 gtk_window_move (GTK_WINDOW (pWidget),
379 pDock->container.iWindowPositionX,
380 pDock->container.iWindowPositionY);
381 }
382 else
383 {
384 pDock->container.iWindowPositionX = pMotion->y_root - pDock->container.iMouseX;
385 pDock->container.iWindowPositionY = pMotion->x_root - pDock->container.iMouseY;
386 gtk_window_move (GTK_WINDOW (pWidget),
387 pDock->container.iWindowPositionY,
388 pDock->container.iWindowPositionX);
389 }
390 gdk_device_get_state (pMotion->device, pMotion->window, NULL, NULL);
391 return FALSE;
392 }
393
394 //\_______________ On recupere la position de la souris.
395 if (pDock->container.bIsHorizontal)
396 {
397 pDock->container.iMouseX = (int) pMotion->x;
398 pDock->container.iMouseY = (int) pMotion->y;
399 }
400 else
401 {
402 pDock->container.iMouseX = (int) pMotion->y;
403 pDock->container.iMouseY = (int) pMotion->x;
404 }
405
406 //\_______________ On tire l'icone volante.
407 if (s_pFlyingContainer != NULL && ! pDock->container.bInside)
408 {
409 gldi_flying_container_drag (s_pFlyingContainer, pDock);
410 }
411
412 //\_______________ On elague le flux des MotionNotify, sinon X en envoie autant que le permet le CPU !
413 if (pMotion->time != 0 && pMotion->time - fLastTime < myBackendsParam.fRefreshInterval && s_pIconClicked == NULL)
414 {
415 gdk_device_get_state (pMotion->device, pMotion->window, NULL, NULL);
416 return FALSE;
417 }
418
419 //\_______________ On recalcule toutes les icones et on redessine.
420 pPointedIcon = cairo_dock_calculate_dock_icons (pDock);
421 //g_print ("pPointedIcon: %s\n", pPointedIcon?pPointedIcon->cName:"none");
422 gtk_widget_queue_draw (pWidget);
423 fLastTime = pMotion->time;
424
425 //\_______________ On tire l'icone cliquee.
426 if (s_pIconClicked != NULL && s_pIconClicked->iAnimationState != CAIRO_DOCK_STATE_REMOVE_INSERT && ! myDocksParam.bLockIcons && ! myDocksParam.bLockAll && (fabs (pMotion->x - s_iClickX) > CD_CLICK_ZONE || fabs (pMotion->y - s_iClickY) > CD_CLICK_ZONE) && ! pDock->bPreventDraggingIcons)
427 {
428 s_bIconDragged = TRUE;
429 cairo_dock_mark_icon_as_following_mouse (s_pIconClicked);
430 //pDock->fAvoidingMouseMargin = .5;
431 pDock->iAvoidingMouseIconType = s_pIconClicked->iGroup; // on pourrait le faire lors du clic aussi.
432 s_pIconClicked->fScale = cairo_dock_get_icon_max_scale (s_pIconClicked);
433 s_pIconClicked->fDrawX = pDock->container.iMouseX - s_pIconClicked->fWidth * s_pIconClicked->fScale / 2;
434 s_pIconClicked->fDrawY = pDock->container.iMouseY - s_pIconClicked->fHeight * s_pIconClicked->fScale / 2 ;
435 s_pIconClicked->fAlpha = 0.75;
436 }
437
438 //gdk_event_request_motions (pMotion); // ce sera pour GDK 2.12.
439 gdk_device_get_state (pMotion->device, pMotion->window, NULL, NULL); // pour recevoir d'autres MotionNotify.
440 }
441 else // cas d'un drag and drop.
442 {
443 //g_print ("motion on drag\n");
444 //\_______________ On recupere la position de la souris.
445 gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock));
446
447 //\_______________ On recalcule toutes les icones et on redessine.
448 pPointedIcon = cairo_dock_calculate_dock_icons (pDock);
449 gtk_widget_queue_draw (pWidget);
450
451 pDock->fAvoidingMouseMargin = .25; // on peut dropper entre 2 icones ...
452 pDock->iAvoidingMouseIconType = CAIRO_DOCK_LAUNCHER; // ... seulement entre 2 icones du groupe "lanceurs".
453 }
454
455 //\_______________ On gere le changement d'icone.
456 gboolean bStartAnimation = FALSE;
457 if (pPointedIcon != pLastPointedIcon)
458 {
459 _on_change_icon (pLastPointedIcon, pPointedIcon, pDock);
460
461 if (pPointedIcon != NULL && s_pIconClicked != NULL && s_pIconClicked->iGroup == pPointedIcon->iGroup && ! myDocksParam.bLockIcons && ! myDocksParam.bLockAll && ! pDock->bPreventDraggingIcons)
462 {
463 _cairo_dock_make_icon_glide (pPointedIcon, s_pIconClicked, pDock);
464 bStartAnimation = TRUE;
465 }
466 }
467
468 //\_______________ On notifie tout le monde.
469 gldi_object_notify (pDock, NOTIFICATION_MOUSE_MOVED, pDock, &bStartAnimation);
470 if (bStartAnimation)
471 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
472
473 return FALSE;
474 }
475
_hide_child_docks(CairoDock * pDock)476 static gboolean _hide_child_docks (CairoDock *pDock)
477 {
478 GList* ic;
479 Icon *icon;
480 for (ic = pDock->icons; ic != NULL; ic = ic->next)
481 {
482 icon = ic->data;
483 if (icon->pSubDock == NULL)
484 continue;
485 if (gldi_container_is_visible (CAIRO_CONTAINER (icon->pSubDock)))
486 {
487 if (icon->pSubDock->container.bInside)
488 {
489 //cd_debug ("on est dans le sous-dock, donc on ne le cache pas");
490 return FALSE;
491 }
492 else if (icon->pSubDock->iSidLeaveDemand == 0) // si on sort du dock sans passer par le sous-dock, par exemple en sortant par le bas.
493 {
494 //cd_debug ("on cache %s par filiation", icon->cName);
495 icon->pSubDock->fFoldingFactor = (myDocksParam.bAnimateSubDock ? 1 : 0); /// 0
496 gtk_widget_hide (icon->pSubDock->container.pWidget);
497 }
498 }
499 }
500 return TRUE;
501 }
502
_on_leave_notify(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventCrossing * pEvent,CairoDock * pDock)503 static gboolean _on_leave_notify (G_GNUC_UNUSED GtkWidget* pWidget, GdkEventCrossing* pEvent, CairoDock *pDock)
504 {
505 //g_print ("%s (bInside:%d; iState:%d; iRefCount:%d)\n", __func__, pDock->container.bInside, pDock->iInputState, pDock->iRefCount);
506 //\_______________ On tire le dock => on ignore le signal.
507 if (pEvent != NULL && (pEvent->state & GDK_MOD1_MASK) && (pEvent->state & GDK_BUTTON1_MASK))
508 {
509 return FALSE;
510 }
511
512 //\_______________ On ignore les signaux errones venant d'un WM buggue (Kwin) ou meme de X (changement de bureau).
513 //if (pEvent)
514 //g_print ("leave event: %d;%d; %d;%d; %d; %d\n", (int)pEvent->x, (int)pEvent->y, (int)pEvent->x_root, (int)pEvent->y_root, pEvent->mode, pEvent->detail);
515 if (pEvent && (pEvent->x != 0 || pEvent->y != 0 || pEvent->x_root != 0 || pEvent->y_root != 0)) // strange leave events occur (detail = GDK_NOTIFY_NONLINEAR, nil coordinates); let's ignore them!
516 {
517 if (pDock->container.bIsHorizontal)
518 {
519 pDock->container.iMouseX = pEvent->x;
520 pDock->container.iMouseY = pEvent->y;
521 }
522 else
523 {
524 pDock->container.iMouseX = pEvent->y;
525 pDock->container.iMouseY = pEvent->x;
526 }
527 }
528 else
529 {
530 //g_print (" forced leave event: %d;%d\n", pDock->container.iMouseX, pDock->container.iMouseY);
531 }
532 if (/**pEvent && */!_mouse_is_really_outside(pDock)) // check that the mouse is really outside (the request might not come from the Window Manager, for instance if we deactivate the menu; this also works around buggy WM like KWin).
533 {
534 //g_print (" not really outside (%d;%d ; %d/%d)\n", pDock->container.iMouseX, pDock->container.iMouseY, pDock->iMaxDockHeight, pDock->iMinDockHeight);
535 if (pDock->iSidTestMouseOutside == 0 && pEvent && ! pDock->bHasModalWindow) // si l'action induit un changement de bureau, ou une appli qui bloque le focus (gksu), X envoit un signal de sortie alors qu'on est encore dans le dock, et donc n'en n'envoit plus lorsqu'on en sort reellement. On teste donc pendant qques secondes apres l'evenement. C'est ausi vrai pour l'affichage d'un menu/dialogue interactif, mais comme on envoie nous-meme un signal de sortie lorsque le menu disparait, il est inutile de le faire ici.
536 {
537 //g_print ("start checking mouse\n");
538 pDock->iSidTestMouseOutside = g_timeout_add (500, (GSourceFunc)_check_mouse_outside, pDock);
539 }
540 return FALSE;
541 }
542
543 //\_______________ On retarde la sortie.
544 if (pEvent != NULL) // sortie naturelle.
545 {
546 if (pDock->iSidLeaveDemand == 0) // pas encore de demande de sortie.
547 {
548 if (pDock->iRefCount == 0) // cas du main dock : on retarde si on pointe sur un sous-dock (pour laisser le temps au signal d'entree dans le sous-dock d'etre traite) ou si l'on a l'auto-hide.
549 {
550 //g_print (" leave event : %.1f;%.1f (%dx%d)\n", pEvent->x, pEvent->y, pDock->container.iWidth, pDock->container.iHeight);
551 Icon *pPointedIcon = cairo_dock_get_pointed_icon (pDock->icons);
552 if (pPointedIcon != NULL && pPointedIcon->pSubDock != NULL && gldi_container_is_visible (CAIRO_CONTAINER (pPointedIcon->pSubDock)))
553 {
554 //g_print (" on retarde la sortie du dock de %dms\n", MAX (myDocksParam.iLeaveSubDockDelay, 330));
555 pDock->iSidLeaveDemand = g_timeout_add (MAX (myDocksParam.iLeaveSubDockDelay, 250), (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pDock);
556 return TRUE;
557 }
558 else if (pDock->bAutoHide)
559 {
560 const int delay = 0; // 250
561 if (delay != 0) /// maybe try to see if we left the dock frankly, or just by a few pixels...
562 {
563 //g_print (" delay the leave event by %dms\n", delay);
564 pDock->iSidLeaveDemand = g_timeout_add (250, (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pDock);
565 return TRUE;
566 }
567 }
568 }
569 else/** if (myDocksParam.iLeaveSubDockDelay != 0)*/ // cas d'un sous-dock : on retarde le cachage.
570 {
571 //g_print (" on retarde la sortie du sous-dock de %dms\n", myDocksParam.iLeaveSubDockDelay);
572 pDock->iSidLeaveDemand = g_timeout_add (MAX (myDocksParam.iLeaveSubDockDelay, 50), (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pDock);
573 //g_print (" -> pDock->iSidLeaveDemand = %d\n", pDock->iSidLeaveDemand);
574 return TRUE;
575 }
576 }
577 else // deja une sortie en attente.
578 {
579 //g_print (" une sortie est deja programmee (%d)\n", pDock->iSidLeaveDemand);
580 return TRUE;
581 }
582 } // sinon c'est nous qui avons explicitement demande cette sortie, donc on continue.
583
584 if (pDock->iSidTestMouseOutside != 0)
585 {
586 //g_print ("stop checking mouse (leave)\n");
587 g_source_remove (pDock->iSidTestMouseOutside);
588 pDock->iSidTestMouseOutside = 0;
589 }
590
591 //\_______________ Arrive ici, on est sorti du dock.
592 pDock->container.bInside = FALSE;
593 pDock->iAvoidingMouseIconType = -1;
594 pDock->fAvoidingMouseMargin = 0;
595
596 //\_______________ On cache ses sous-docks.
597 if (! _hide_child_docks (pDock)) // on quitte si l'un des sous-docks reste visible (on est entre dedans), pour rester en position "haute".
598 {
599 //g_print (" un des sous-docks reste visible");
600 return TRUE;
601 }
602
603 if (pDock->iRefCount != 0) // sub-dock -> if the main icon is currently pointed, and doesn't have a dialog that would be in the way, stay visible
604 {
605 CairoDock *pParentDock = NULL;
606 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pParentDock);
607 if (pPointingIcon && pParentDock)
608 {
609 if (pPointingIcon->bPointed && pParentDock->container.bInside && ! gldi_icon_has_dialog (pPointingIcon))
610 {
611 //g_print (" the main icon is currently pointed, stay visible\n");
612 return TRUE;
613 }
614 }
615 }
616
617 if (s_iSidShowSubDockDemand != 0 && (pDock->iRefCount == 0 || s_pSubDockShowing == pDock)) // si ce dock ou l'un des sous-docks etait programme pour se montrer, on annule.
618 {
619 g_source_remove (s_iSidShowSubDockDemand);
620 s_iSidShowSubDockDemand = 0;
621 s_pDockShowingSubDock = NULL;
622 s_pSubDockShowing = NULL;
623 }
624
625 //\_______________ If a modal window is raised, we discard the 'leave-event' to stay in the up position.
626 if (pDock->bHasModalWindow)
627 return TRUE;
628
629 //\_______________ On gere le drag d'une icone hors du dock.
630 if (s_pIconClicked != NULL
631 && (CAIRO_DOCK_ICON_TYPE_IS_LAUNCHER (s_pIconClicked)
632 || CAIRO_DOCK_ICON_TYPE_IS_CONTAINER (s_pIconClicked)
633 || (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (s_pIconClicked) && s_pIconClicked->cDesktopFileName && pDock->iMaxDockHeight > 30) // if the dock is narrow (like a panel), prevent from dragging separators outside of the dock. TODO: maybe we need a parameter in the view...
634 || CAIRO_DOCK_IS_DETACHABLE_APPLET (s_pIconClicked))
635 && s_pFlyingContainer == NULL
636 && ! myDocksParam.bLockIcons
637 && ! myDocksParam.bLockAll
638 && ! pDock->bPreventDraggingIcons)
639 {
640 cd_debug ("on a sorti %s du dock (%d;%d) / %dx%d", s_pIconClicked->cName, pDock->container.iMouseX, pDock->container.iMouseY, pDock->container.iWidth, pDock->container.iHeight);
641
642 //if (! _hide_child_docks (pDock)) // on quitte si on entre dans un sous-dock, pour rester en position "haute".
643 // return ;
644
645 CairoDock *pOriginDock = CAIRO_DOCK(cairo_dock_get_icon_container (s_pIconClicked));
646 if (pOriginDock == pDock && _mouse_is_really_outside (pDock)) // ce test est la pour parer aux WM deficients mentaux comme KWin qui nous font sortir/rentrer lors d'un clic.
647 {
648 cd_debug (" on detache l'icone");
649 pOriginDock->bIconIsFlyingAway = TRUE;
650 gldi_icon_detach (s_pIconClicked);
651 cairo_dock_stop_icon_glide (pOriginDock);
652
653 s_pFlyingContainer = gldi_flying_container_new (s_pIconClicked, pOriginDock);
654 //g_print ("- s_pIconClicked <- NULL\n");
655 s_pIconClicked = NULL;
656 if (pDock->iRefCount > 0 || pDock->bAutoHide) // pour garder le dock visible.
657 {
658 return TRUE;
659 }
660 }
661 }
662 /**else if (s_pFlyingContainer != NULL && s_pFlyingContainer->pIcon != NULL && pDock->iRefCount > 0) // on evite les bouclages.
663 {
664 CairoDock *pOriginDock = gldi_dock_get (s_pFlyingContainer->pIcon->cParentDockName);
665 if (pOriginDock == pDock)
666 return GLDI_NOTIFICATION_INTERCEPT;
667 }*/
668
669 gboolean bStartAnimation = FALSE;
670 gldi_object_notify (pDock, NOTIFICATION_LEAVE_DOCK, pDock, &bStartAnimation);
671 if (bStartAnimation)
672 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
673
674 return TRUE;
675 }
676
_on_enter_notify(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventCrossing * pEvent,CairoDock * pDock)677 static gboolean _on_enter_notify (G_GNUC_UNUSED GtkWidget* pWidget, GdkEventCrossing* pEvent, CairoDock *pDock)
678 {
679 //g_print ("%s (bIsMainDock : %d; bInside:%d; state:%d; iMagnitudeIndex:%d; input shape:%p; event:%p)\n", __func__, pDock->bIsMainDock, pDock->container.bInside, pDock->iInputState, pDock->iMagnitudeIndex, pDock->pShapeBitmap, pEvent);
680 if (! cairo_dock_entrance_is_allowed (pDock))
681 {
682 cd_message ("* entree non autorisee");
683 return FALSE;
684 }
685
686 // stop les timers.
687 if (pDock->iSidLeaveDemand != 0)
688 {
689 g_source_remove (pDock->iSidLeaveDemand);
690 pDock->iSidLeaveDemand = 0;
691 }
692 if (s_iSidShowSubDockDemand != 0) // gere un cas tordu mais bien reel.
693 {
694 g_source_remove (s_iSidShowSubDockDemand);
695 s_iSidShowSubDockDemand = 0;
696 }
697 if (pDock->iSidHideBack != 0)
698 {
699 //g_print ("remove hide back timeout\n");
700 g_source_remove (pDock->iSidHideBack);
701 pDock->iSidHideBack = 0;
702 }
703 if (pDock->iSidTestMouseOutside != 0)
704 {
705 //g_print ("stop checking mouse (enter)\n");
706 g_source_remove (pDock->iSidTestMouseOutside);
707 pDock->iSidTestMouseOutside = 0;
708 }
709
710 // input shape desactivee, le dock devient actif.
711 if ((pDock->pShapeBitmap || pDock->pHiddenShapeBitmap) && pDock->iInputState != CAIRO_DOCK_INPUT_ACTIVE)
712 {
713 //g_print ("+++ input shape active on enter\n");
714 cairo_dock_set_input_shape_active (pDock);
715 }
716 pDock->iInputState = CAIRO_DOCK_INPUT_ACTIVE;
717
718 // si on etait deja dedans, ou qu'on etait cense l'etre, on relance juste le grossissement.
719 /**if (pDock->container.bInside || pDock->bIsHiding)
720 {
721 pDock->container.bInside = TRUE;
722 cairo_dock_start_growing (pDock);
723 if (pDock->bIsHiding || cairo_dock_is_hidden (pDock)) // on (re)monte.
724 {
725 cd_debug (" on etait deja dedans\n");
726 cairo_dock_start_showing (pDock);
727 }
728 return FALSE;
729 }*/
730
731 gboolean bWasInside = pDock->container.bInside;
732 pDock->container.bInside = TRUE;
733
734 // animation d'entree.
735 gboolean bStartAnimation = FALSE;
736 gldi_object_notify (pDock, NOTIFICATION_ENTER_DOCK, pDock, &bStartAnimation);
737 if (bStartAnimation)
738 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
739
740 pDock->fDecorationsOffsetX = 0;
741 cairo_dock_stop_quick_hide ();
742
743 if (s_pIconClicked != NULL) // on pourrait le faire a chaque motion aussi.
744 {
745 pDock->iAvoidingMouseIconType = s_pIconClicked->iGroup;
746 pDock->fAvoidingMouseMargin = .5; /// inutile il me semble ...
747 }
748
749 // si on rentre avec une icone volante, on la met dedans.
750 if (s_pFlyingContainer != NULL)
751 {
752 Icon *pFlyingIcon = s_pFlyingContainer->pIcon;
753 if (pDock != pFlyingIcon->pSubDock) // on evite les boucles.
754 {
755 struct timeval tv;
756 int r = gettimeofday (&tv, NULL);
757 double t = 0.;
758 if (r == 0)
759 t = tv.tv_sec + tv.tv_usec * 1e-6;
760 if (t - s_pFlyingContainer->fCreationTime > 1) // on empeche le cas ou enlever l'icone fait augmenter le ratio du dock, et donc sa hauteur, et nous fait rentrer dedans des qu'on sort l'icone.
761 {
762 //g_print ("on remet l'icone volante dans un dock (dock d'origine : %s)\n", pFlyingIcon->cParentDockName);
763 gldi_object_unref (GLDI_OBJECT(s_pFlyingContainer)); // will detach the icon
764 gldi_icon_stop_animation (pFlyingIcon);
765 // reinsert the icon where it was dropped, not at its original position.
766 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons); // get the pointed icon before we insert the icon, since the inserted icon will be the pointed one!
767 //g_print (" pointed icon: %s\n", icon?icon->cName:"none");
768 gldi_icon_insert_in_container (pFlyingIcon, CAIRO_CONTAINER(pDock), CAIRO_DOCK_ANIMATE_ICON);
769 if (icon != NULL && cairo_dock_get_icon_order (icon) == cairo_dock_get_icon_order (pFlyingIcon))
770 {
771 cairo_dock_move_icon_after_icon (pDock, pFlyingIcon, icon);
772 }
773 s_pFlyingContainer = NULL;
774 pDock->bIconIsFlyingAway = FALSE;
775 }
776 }
777 }
778
779 // si on etait derriere, on repasse au premier plan.
780 if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && pDock->bIsBelow && pDock->iRefCount == 0)
781 {
782 cairo_dock_pop_up (pDock);
783 }
784
785 // si on etait cache (entierement ou partiellement), on montre.
786 if ((pDock->bIsHiding || cairo_dock_is_hidden (pDock)) && pDock->iRefCount == 0)
787 {
788 //g_print (" on commence a monter\n");
789 cairo_dock_start_showing (pDock); // on a mis a jour la zone d'input avant, sinon la fonction le ferait, ce qui serait inutile.
790 }
791
792 // start growing up (do it before calculating icons, so that we don't seem to be in an anormal state, where we're inside a dock that doesn't grow).
793 cairo_dock_start_growing (pDock);
794
795 // since we've just entered the dock, the pointed icon has changed from none to the current one.
796 if (pEvent != NULL && ! bWasInside)
797 {
798 // update the mouse coordinates
799 if (pDock->container.bIsHorizontal)
800 {
801 pDock->container.iMouseX = (int) pEvent->x;
802 pDock->container.iMouseY = (int) pEvent->y;
803 }
804 else
805 {
806 pDock->container.iMouseX = (int) pEvent->y;
807 pDock->container.iMouseY = (int) pEvent->x;
808 }
809 // then compute the icons (especially the pointed one).
810 Icon *icon = cairo_dock_calculate_dock_icons (pDock); // returns the pointed icon
811 // trigger the change to trigger the animation and sub-dock popup
812 if (icon != NULL)
813 {
814 _on_change_icon (NULL, icon, pDock); // we were out of the dock, so there is no previous pointed icon.
815 }
816 }
817
818 return TRUE;
819 }
820
821
_on_key_release(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventKey * pKey,CairoDock * pDock)822 static gboolean _on_key_release (G_GNUC_UNUSED GtkWidget *pWidget,
823 GdkEventKey *pKey,
824 CairoDock *pDock)
825 {
826 cd_debug ("on a appuye sur une touche (%d/%d)", pKey->keyval, pKey->hardware_keycode);
827 if (pKey->type == GDK_KEY_PRESS)
828 {
829 gldi_object_notify (pDock, NOTIFICATION_KEY_PRESSED, pDock, pKey->keyval, pKey->state, pKey->string, pKey->hardware_keycode);
830 }
831 else if (pKey->type == GDK_KEY_RELEASE)
832 {
833 //g_print ("release : pKey->keyval = %d\n", pKey->keyval);
834 if ((pKey->state & GDK_MOD1_MASK) && pKey->keyval == 0) // On relache la touche ALT, typiquement apres avoir fait un ALT + clique gauche + deplacement.
835 {
836 if (pDock->iRefCount == 0 && pDock->iVisibility != CAIRO_DOCK_VISI_SHORTKEY)
837 gldi_rootdock_write_gaps (pDock);
838 }
839 }
840 return TRUE;
841 }
842
843
_double_click_delay_over(Icon * icon)844 static gboolean _double_click_delay_over (Icon *icon)
845 {
846 CairoDock *pDock = CAIRO_DOCK (cairo_dock_get_icon_container(icon));
847 if (pDock)
848 {
849 gldi_icon_stop_attention (icon); // we consider that clicking on the icon is an acknowledge of the demand of attention.
850 pDock->container.iMouseX = s_iFirstClickX;
851 pDock->container.iMouseY = s_iFirstClickY;
852 gldi_object_notify (pDock, NOTIFICATION_CLICK_ICON, icon, pDock, GDK_BUTTON1_MASK);
853
854 gldi_icon_start_animation (icon);
855 }
856 icon->iSidDoubleClickDelay = 0;
857 return FALSE;
858 }
_check_mouse_outside(CairoDock * pDock)859 static gboolean _check_mouse_outside (CairoDock *pDock) // ce test est principalement fait pour detecter les cas ou X nous envoit un signal leave errone alors qu'on est dedans (=> sortie refusee, bInside reste a TRUE), puis du coup ne nous en envoit pas de leave lorsqu'on quitte reellement le dock.
860 {
861 // g_print (" %s (%d, %d, %d)\n", __func__, pDock->bIsShrinkingDown, pDock->iMagnitudeIndex, pDock->container.bInside);
862 if (pDock->bIsShrinkingDown || pDock->iMagnitudeIndex == 0 || ! pDock->container.bInside) // trivial cases : if the dock has already shrunk, or we're not inside any more, we can quit the loop.
863 {
864 pDock->iSidTestMouseOutside = 0;
865 return FALSE;
866 }
867
868 gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock));
869 // g_print (" -> (%d, %d)\n", pDock->container.iMouseX, pDock->container.iMouseY);
870
871 cairo_dock_calculate_dock_icons (pDock); // pour faire retrecir le dock si on n'est pas dedans, merci X de nous faire sortir du dock alors que la souris est toujours dedans :-/
872 return TRUE;
873 }
_on_button_press(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventButton * pButton,CairoDock * pDock)874 static gboolean _on_button_press (G_GNUC_UNUSED GtkWidget* pWidget, GdkEventButton* pButton, CairoDock *pDock)
875 {
876 //g_print ("+ %s (%d/%d, %x)\n", __func__, pButton->type, pButton->button, pWidget);
877 if (pDock->container.bIsHorizontal) // utile ?
878 {
879 pDock->container.iMouseX = (int) pButton->x;
880 pDock->container.iMouseY = (int) pButton->y;
881 }
882 else
883 {
884 pDock->container.iMouseX = (int) pButton->y;
885 pDock->container.iMouseY = (int) pButton->x;
886 }
887
888 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons);
889 if (pButton->button == 1) // clic gauche.
890 {
891 //g_print ("+ left click\n");
892 switch (pButton->type)
893 {
894 case GDK_BUTTON_RELEASE :
895 //g_print ("+ GDK_BUTTON_RELEASE (%d/%d sur %s/%s)\n", pButton->state, GDK_CONTROL_MASK | GDK_MOD1_MASK, icon ? icon->cName : "personne", icon ? icon->cCommand : ""); // 272 = 100010000
896 if (pDock->container.bIgnoreNextReleaseEvent)
897 {
898 pDock->container.bIgnoreNextReleaseEvent = FALSE;
899 s_pIconClicked = NULL;
900 s_bIconDragged = FALSE;
901 return TRUE;
902 }
903
904 if ( ! (pButton->state & GDK_MOD1_MASK))
905 {
906 if (s_pIconClicked != NULL)
907 {
908 cd_debug ("activate %s (%s)", s_pIconClicked->cName, icon ? icon->cName : "none");
909 s_pIconClicked->iAnimationState = CAIRO_DOCK_STATE_REST; // stoppe les animations de suivi du curseur.
910 pDock->iAvoidingMouseIconType = -1;
911 cairo_dock_stop_icon_glide (pDock);
912 }
913 if (icon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) && icon == s_pIconClicked) // released the button on the clicked icon => trigger the CLICK signal.
914 {
915 s_pIconClicked = NULL; // il faut le faire ici au cas ou le clic induirait un dialogue bloquant qui nous ferait sortir du dock par exemple.
916 //g_print ("+ click on '%s' (%s)\n", icon->cName, icon->cCommand);
917 if (! s_bIconDragged) // on ignore le drag'n'drop sur elle-meme.
918 {
919 if (icon->iNbDoubleClickListeners > 0)
920 {
921 if (icon->iSidDoubleClickDelay == 0) // 1er release.
922 {
923 icon->iSidDoubleClickDelay = g_timeout_add (CD_DOUBLE_CLICK_DELAY, (GSourceFunc)_double_click_delay_over, icon);
924 s_iFirstClickX = pDock->container.iMouseX; // the mouse can move between the first and the second clicks; since the event is triggered when the second click occurs, the coordinates may be wrong -> we have to remember the position of the first click.
925 s_iFirstClickY = pDock->container.iMouseY;
926 }
927 }
928 else
929 {
930 gldi_icon_stop_attention (icon); // we consider that clicking on the icon is an acknowledge of the demand of attention.
931
932 gldi_object_notify (pDock, NOTIFICATION_CLICK_ICON, icon, pDock, pButton->state);
933
934 gldi_icon_start_animation (icon);
935 }
936 }
937 }
938 else if (s_pIconClicked != NULL && icon != NULL && icon != s_pIconClicked && ! myDocksParam.bLockIcons && ! myDocksParam.bLockAll && ! pDock->bPreventDraggingIcons) // released the icon on another one.
939 {
940 //g_print ("deplacement de %s\n", s_pIconClicked->cName);
941 CairoDock *pOriginDock = CAIRO_DOCK (cairo_dock_get_icon_container (s_pIconClicked));
942 if (pOriginDock != NULL && pDock != pOriginDock)
943 {
944 gldi_icon_detach (s_pIconClicked);
945
946 gldi_theme_icon_write_container_name_in_conf_file (s_pIconClicked, gldi_dock_get_name (pDock));
947
948 gldi_icon_insert_in_container (s_pIconClicked, CAIRO_CONTAINER(pDock), CAIRO_DOCK_ANIMATE_ICON);
949 }
950
951 Icon *prev_icon, *next_icon;
952 if (icon->fXAtRest > s_pIconClicked->fXAtRest)
953 {
954 prev_icon = icon;
955 next_icon = cairo_dock_get_next_icon (pDock->icons, icon);
956 }
957 else
958 {
959 prev_icon = cairo_dock_get_previous_icon (pDock->icons, icon);
960 next_icon = icon;
961 }
962 if (icon->iGroup != s_pIconClicked->iGroup
963 && (prev_icon == NULL || prev_icon->iGroup != s_pIconClicked->iGroup)
964 && (next_icon == NULL || next_icon->iGroup != s_pIconClicked->iGroup))
965 {
966 s_pIconClicked = NULL;
967 return FALSE;
968 }
969 //g_print ("deplacement de %s\n", s_pIconClicked->cName);
970 ///if (prev_icon != NULL && prev_icon->iGroup != s_pIconClicked->iGroup) // the previous icon is in a different group -> we'll be at the beginning of our group.
971 /// prev_icon = NULL; // => move to the beginning of the group/dock
972 cairo_dock_move_icon_after_icon (pDock, s_pIconClicked, prev_icon);
973
974 cairo_dock_calculate_dock_icons (pDock);
975
976 if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (s_pIconClicked))
977 {
978 gldi_icon_request_animation (s_pIconClicked, "bounce", 2);
979 }
980 gtk_widget_queue_draw (pDock->container.pWidget);
981 }
982
983 if (s_pFlyingContainer != NULL) // the user released the flying icon -> detach/destroy it, or insert it
984 {
985 cd_debug ("on relache l'icone volante");
986 if (pDock->container.bInside)
987 {
988 //g_print (" on la remet dans son dock d'origine\n");
989 Icon *pFlyingIcon = s_pFlyingContainer->pIcon;
990 gldi_object_unref (GLDI_OBJECT(s_pFlyingContainer));
991 cairo_dock_stop_marking_icon_as_following_mouse (pFlyingIcon);
992 // reinsert the icon where it was dropped, not at its original position.
993 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons); // get the pointed icon before we insert the icon, since the inserted icon will be the pointed one!
994 gldi_icon_insert_in_container (pFlyingIcon, CAIRO_CONTAINER(pDock), CAIRO_DOCK_ANIMATE_ICON);
995 if (icon != NULL && cairo_dock_get_icon_order (icon) == cairo_dock_get_icon_order (pFlyingIcon))
996 {
997 cairo_dock_move_icon_after_icon (pDock, pFlyingIcon, icon);
998 }
999 }
1000 else
1001 {
1002 gldi_flying_container_terminate (s_pFlyingContainer); // supprime ou detache l'icone, l'animation se terminera toute seule.
1003 }
1004 s_pFlyingContainer = NULL;
1005 pDock->bIconIsFlyingAway = FALSE;
1006 cairo_dock_stop_icon_glide (pDock);
1007 }
1008 /// a implementer ...
1009 ///gldi_object_notify (CAIRO_CONTAINER (pDock), CAIRO_DOCK_RELEASE_ICON, icon, pDock);
1010 }
1011 else
1012 {
1013 if (pDock->iRefCount == 0 && pDock->iVisibility != CAIRO_DOCK_VISI_SHORTKEY)
1014 gldi_rootdock_write_gaps (pDock);
1015 }
1016 //g_print ("- apres clic : s_pIconClicked <- NULL\n");
1017 s_pIconClicked = NULL;
1018 s_bIconDragged = FALSE;
1019 break ;
1020
1021 case GDK_BUTTON_PRESS :
1022 if ( ! (pButton->state & GDK_MOD1_MASK))
1023 {
1024 //g_print ("+ clic sur %s (%.2f)!\n", icon ? icon->cName : "rien", icon ? icon->fInsertRemoveFactor : 0.);
1025 s_iClickX = pButton->x;
1026 s_iClickY = pButton->y;
1027 if (icon && ! cairo_dock_icon_is_being_removed (icon) && ! CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (icon))
1028 {
1029 s_pIconClicked = icon; // on ne definit pas l'animation FOLLOW_MOUSE ici , on le fera apres le 1er mouvement, pour eviter que l'icone soit dessinee comme tel quand on clique dessus alors que le dock est en train de jouer une animation (ca provoque un flash desagreable).
1030 cd_debug ("clicked on %s", icon->cName);
1031 }
1032 else
1033 s_pIconClicked = NULL;
1034 }
1035 break ;
1036
1037 case GDK_2BUTTON_PRESS :
1038 if (icon && ! cairo_dock_icon_is_being_removed (icon))
1039 {
1040 if (icon->iSidDoubleClickDelay != 0)
1041 {
1042 g_source_remove (icon->iSidDoubleClickDelay);
1043 icon->iSidDoubleClickDelay = 0;
1044 }
1045 gldi_object_notify (pDock, NOTIFICATION_DOUBLE_CLICK_ICON, icon, pDock);
1046 if (icon->iNbDoubleClickListeners > 0)
1047 pDock->container.bIgnoreNextReleaseEvent = TRUE;
1048 }
1049 break ;
1050
1051 default :
1052 break ;
1053 }
1054 }
1055 else if (pButton->button == 3 && pButton->type == GDK_BUTTON_PRESS) // clique droit.
1056 {
1057 GtkWidget *menu = gldi_container_build_menu (CAIRO_CONTAINER (pDock), icon); // genere un CAIRO_DOCK_BUILD_CONTAINER_MENU et CAIRO_DOCK_BUILD_ICON_MENU.
1058
1059 gldi_menu_popup (menu);
1060 }
1061 else if (pButton->button == 2 && pButton->type == GDK_BUTTON_PRESS) // clique milieu.
1062 {
1063 if (icon && ! cairo_dock_icon_is_being_removed (icon))
1064 {
1065 gldi_object_notify (pDock, NOTIFICATION_MIDDLE_CLICK_ICON, icon, pDock);
1066 }
1067 }
1068
1069 return FALSE;
1070 }
1071
1072
_on_scroll(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventScroll * pScroll,CairoDock * pDock)1073 static gboolean _on_scroll (G_GNUC_UNUSED GtkWidget* pWidget, GdkEventScroll* pScroll, CairoDock *pDock)
1074 {
1075 if (pScroll->direction != GDK_SCROLL_UP && pScroll->direction != GDK_SCROLL_DOWN) // on degage les scrolls horizontaux.
1076 {
1077 return FALSE;
1078 }
1079 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons); // can be NULL
1080 gldi_object_notify (pDock, NOTIFICATION_SCROLL_ICON, icon, pDock, pScroll->direction);
1081
1082 return FALSE;
1083 }
1084
1085
_on_configure(GtkWidget * pWidget,GdkEventConfigure * pEvent,CairoDock * pDock)1086 static gboolean _on_configure (GtkWidget* pWidget, GdkEventConfigure* pEvent, CairoDock *pDock)
1087 {
1088 //g_print ("%s (%p, main dock : %d) : (%d;%d) (%dx%d)\n", __func__, pDock, pDock->bIsMainDock, pEvent->x, pEvent->y, pEvent->width, pEvent->height);
1089 // set the new actual size of the container
1090 gint iNewWidth, iNewHeight, iNewX, iNewY;
1091 if (pDock->container.bIsHorizontal)
1092 {
1093 iNewWidth = pEvent->width;
1094 iNewHeight = pEvent->height;
1095
1096 iNewX = pEvent->x;
1097 iNewY = pEvent->y;
1098 }
1099 else
1100 {
1101 iNewWidth = pEvent->height;
1102 iNewHeight = pEvent->width;
1103
1104 iNewX = pEvent->y;
1105 iNewY = pEvent->x;
1106 }
1107
1108 gboolean bSizeUpdated = (iNewWidth != pDock->container.iWidth || iNewHeight != pDock->container.iHeight);
1109 ///gboolean bIsNowSized = (pDock->container.iWidth == 1 && pDock->container.iHeight == 1 && bSizeUpdated);
1110 gboolean bPositionUpdated = (pDock->container.iWindowPositionX != iNewX || pDock->container.iWindowPositionY != iNewY);
1111 pDock->container.iWidth = iNewWidth;
1112 pDock->container.iHeight = iNewHeight;
1113 pDock->container.iWindowPositionX = iNewX;
1114 pDock->container.iWindowPositionY = iNewY;
1115
1116 if (pDock->container.iWidth == 1 && pDock->container.iHeight == 1) // the X window has not yet reached its size.
1117 {
1118 return FALSE;
1119 }
1120
1121 // if the size has changed, also update everything that depends on it.
1122 if (bSizeUpdated) // changement de taille
1123 {
1124 // update mouse relative position inside the window
1125 gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock));
1126 if (pDock->container.iMouseX < 0 || pDock->container.iMouseX > pDock->container.iWidth) // utile ?
1127 pDock->container.iMouseX = 0;
1128
1129 // update the input shape (it has been calculated in the function that made the resize)
1130 cairo_dock_update_input_shape (pDock);
1131 switch (pDock->iInputState) // update the input zone
1132 {
1133 case CAIRO_DOCK_INPUT_ACTIVE:
1134 cairo_dock_set_input_shape_active (pDock);
1135 break;
1136 case CAIRO_DOCK_INPUT_AT_REST:
1137 cairo_dock_set_input_shape_at_rest (pDock);
1138 break;
1139 case CAIRO_DOCK_INPUT_HIDDEN:
1140 cairo_dock_set_input_shape_hidden (pDock);
1141 break;
1142 default:
1143 break;
1144 }
1145
1146 // update the GL context
1147 if (g_bUseOpenGL)
1148 {
1149 if (! gldi_gl_container_make_current (CAIRO_CONTAINER (pDock)))
1150 return FALSE;
1151
1152 gldi_gl_container_set_ortho_view (CAIRO_CONTAINER (pDock));
1153
1154 glClearAccum (0., 0., 0., 0.);
1155 glClear (GL_ACCUM_BUFFER_BIT);
1156
1157 if (pDock->iRedirectedTexture != 0)
1158 {
1159 _cairo_dock_delete_texture (pDock->iRedirectedTexture);
1160 pDock->iRedirectedTexture = cairo_dock_create_texture_from_raw_data (NULL, pEvent->width, pEvent->height);
1161 }
1162 }
1163
1164 cairo_dock_calculate_dock_icons (pDock);
1165 //g_print ("configure size %s\n", pDock->cDockName);
1166 cairo_dock_trigger_set_WM_icons_geometry (pDock); // changement de position ou de taille du dock => on replace les icones.
1167
1168 gldi_dialogs_replace_all ();
1169
1170 if (/**bIsNowSized*/bSizeUpdated && g_bUseOpenGL) // in OpenGL, the context is linked to the window; now that the window has a correct size, the context is ready -> draw things that couldn't be drawn until now.
1171 {
1172 Icon *icon;
1173 GList *ic;
1174 for (ic = pDock->icons; ic != NULL; ic = ic->next)
1175 {
1176 icon = ic->data;
1177 gboolean bDamaged = icon->bDamaged; // if bNeedApplyBackground is also TRUE, applying the background will remove the 'damage' flag.
1178 if (icon->bNeedApplyBackground) // if both are TRUE, we need to do both (for instance, the data-renderer might not redraw the icon (progressbar)). draw the bg first so that we don't draw it twice.
1179 {
1180 icon->bNeedApplyBackground = FALSE; // set to FALSE, if it doesn't work here, it will probably never do.
1181 cairo_dock_apply_icon_background_opengl (icon);
1182 }
1183 if (bDamaged)
1184 {
1185 //g_print ("This icon %s is damaged (%d)\n", icon->cName, icon->iSubdockViewType);
1186 icon->bDamaged = FALSE;
1187 if (cairo_dock_get_icon_data_renderer (icon) != NULL)
1188 {
1189 cairo_dock_refresh_data_renderer (icon, CAIRO_CONTAINER (pDock));
1190 }
1191 else if (icon->iSubdockViewType != 0
1192 || (icon->cClass != NULL && ! myIndicatorsParam.bUseClassIndic && (CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (icon) || GLDI_OBJECT_IS_LAUNCHER_ICON (icon))))
1193 {
1194 cairo_dock_draw_subdock_content_on_icon (icon, pDock);
1195 }
1196 else if (CAIRO_DOCK_IS_APPLET (icon))
1197 {
1198 gldi_object_reload (GLDI_OBJECT(icon->pModuleInstance), FALSE); // easy but safe way to redraw the icon properly.
1199 }
1200 else // if we don't know how the icon should be drawn, just reload it.
1201 {
1202 cairo_dock_load_icon_image (icon, CAIRO_CONTAINER (pDock));
1203 }
1204 if (pDock->iRefCount != 0) // now that the icon image is correct, redraw the pointing icon if needed
1205 cairo_dock_trigger_redraw_subdock_content (pDock);
1206 }
1207 }
1208 }
1209 }
1210 else if (bPositionUpdated) // changement de position.
1211 {
1212 //g_print ("configure x,y\n");
1213 cairo_dock_trigger_set_WM_icons_geometry (pDock); // changement de position de la fenetre du dock => on replace les icones.
1214
1215 gldi_dialogs_replace_all ();
1216 }
1217
1218 if (pDock->iRefCount == 0 && (bSizeUpdated || bPositionUpdated))
1219 {
1220 if (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP)
1221 {
1222 GldiWindowActor *pActiveAppli = gldi_windows_get_active ();
1223 if (_gldi_window_is_on_our_way (pActiveAppli, pDock)) // la fenetre active nous gene.
1224 {
1225 if (!cairo_dock_is_temporary_hidden (pDock))
1226 cairo_dock_activate_temporary_auto_hide (pDock);
1227 }
1228 else
1229 {
1230 if (cairo_dock_is_temporary_hidden (pDock))
1231 cairo_dock_deactivate_temporary_auto_hide (pDock);
1232 }
1233 }
1234 else if (pDock->iVisibility == CAIRO_DOCK_VISI_AUTO_HIDE_ON_OVERLAP_ANY)
1235 {
1236 if (gldi_dock_search_overlapping_window (pDock) != NULL)
1237 {
1238 if (!cairo_dock_is_temporary_hidden (pDock))
1239 cairo_dock_activate_temporary_auto_hide (pDock);
1240 }
1241 else
1242 {
1243 if (cairo_dock_is_temporary_hidden (pDock))
1244 cairo_dock_deactivate_temporary_auto_hide (pDock);
1245 }
1246 }
1247 }
1248
1249 gtk_widget_queue_draw (pWidget);
1250
1251 return FALSE;
1252 }
1253
1254
1255
1256 static gboolean s_bWaitForData = FALSE;
1257 static gboolean s_bCouldDrop = FALSE;
1258
_on_drag_data_received(G_GNUC_UNUSED GtkWidget * pWidget,GdkDragContext * dc,gint x,gint y,GtkSelectionData * selection_data,G_GNUC_UNUSED guint info,guint time,CairoDock * pDock)1259 void _on_drag_data_received (G_GNUC_UNUSED GtkWidget *pWidget, GdkDragContext *dc, gint x, gint y, GtkSelectionData *selection_data, G_GNUC_UNUSED guint info, guint time, CairoDock *pDock)
1260 {
1261 cd_debug ("%s (%dx%d, %d, %d)", __func__, x, y, time, pDock->container.bInside);
1262 if (cairo_dock_is_hidden (pDock)) // X ne semble pas tenir compte de la zone d'input pour dropper les trucs...
1263 return ;
1264 //\_________________ On recupere l'URI.
1265 gchar *cReceivedData = (gchar *)gtk_selection_data_get_data (selection_data); // the data are actually 'const guchar*', but since we only allowed text and urls, it will be a string
1266 g_return_if_fail (cReceivedData != NULL);
1267 int length = strlen (cReceivedData);
1268 if (cReceivedData[length-1] == '\n')
1269 cReceivedData[--length] = '\0'; // on vire le retour chariot final.
1270 if (cReceivedData[length-1] == '\r')
1271 cReceivedData[--length] = '\0';
1272
1273 if (s_bWaitForData)
1274 {
1275 s_bWaitForData = FALSE;
1276 gdk_drag_status (dc, GDK_ACTION_COPY, time);
1277 cd_debug ("drag info : <%s>", cReceivedData);
1278 pDock->iAvoidingMouseIconType = CAIRO_DOCK_LAUNCHER;
1279 if (g_str_has_suffix (cReceivedData, ".desktop")/** || g_str_has_suffix (cReceivedData, ".sh")*/)
1280 pDock->fAvoidingMouseMargin = .5; // on ne sera jamais dessus.
1281 else
1282 pDock->fAvoidingMouseMargin = .25;
1283 return ;
1284 }
1285
1286 //\_________________ On arrete l'animation.
1287 //cairo_dock_stop_marking_icons (pDock);
1288 pDock->iAvoidingMouseIconType = -1;
1289 pDock->fAvoidingMouseMargin = 0;
1290
1291 //\_________________ On arrete le timer.
1292 if (s_iSidActionOnDragHover != 0)
1293 {
1294 //cd_debug ("on annule la demande de montrage d'appli");
1295 g_source_remove (s_iSidActionOnDragHover);
1296 s_iSidActionOnDragHover = 0;
1297 }
1298
1299 //\_________________ On calcule la position a laquelle on l'a lache.
1300 cd_debug (">>> cReceivedData : '%s' (%d/%d)", cReceivedData, s_bCouldDrop, pDock->bCanDrop);
1301 /* icon => drop on icon
1302 no icon => if order undefined: drop on dock; else: drop between 2 icons.*/
1303 Icon *pPointedIcon = NULL;
1304 double fOrder;
1305 if (s_bCouldDrop) // can drop on the dock
1306 {
1307 cd_debug ("drop between icons");
1308
1309 pPointedIcon = NULL;
1310 fOrder = 0;
1311
1312 // try to guess where we dropped.
1313 int iDropX = (pDock->container.bIsHorizontal ? x : y);
1314 Icon *pNeighboorIcon;
1315 Icon *icon = NULL;
1316 GList *ic;
1317 for (ic = pDock->icons; ic != NULL; ic = ic->next)
1318 {
1319 icon = ic->data;
1320 if (icon->bPointed)
1321 {
1322 if (iDropX < icon->fDrawX + icon->fWidth * icon->fScale/2) // on the left side of the icon
1323 {
1324 pNeighboorIcon = (ic->prev != NULL ? ic->prev->data : NULL);
1325 fOrder = (pNeighboorIcon != NULL ? (icon->fOrder + pNeighboorIcon->fOrder) / 2 : icon->fOrder - 1);
1326 }
1327 else // on the right side of the icon
1328 {
1329 pNeighboorIcon = (ic->next != NULL ? ic->next->data : NULL);
1330 fOrder = (pNeighboorIcon != NULL ? (icon->fOrder + pNeighboorIcon->fOrder) / 2 : icon->fOrder + 1);
1331 }
1332 break;
1333 }
1334 }
1335 if (myDocksParam.bLockAll) // locked, can't add anything.
1336 {
1337 gldi_dialog_show_temporary_with_default_icon (_("Sorry but the dock is locked"), icon, CAIRO_CONTAINER (pDock), 5000);
1338 gtk_drag_finish (dc, FALSE, FALSE, time);
1339 return ;
1340 }
1341 }
1342 else // drop on an icon or nowhere.
1343 {
1344 pPointedIcon = cairo_dock_get_pointed_icon (pDock->icons);
1345 fOrder = CAIRO_DOCK_LAST_ORDER;
1346 if (pPointedIcon == NULL && ! g_str_has_suffix (cReceivedData, ".desktop")) // no icon => abort, but .desktop are always added
1347 {
1348 cd_debug ("drop nowhere");
1349 gtk_drag_finish (dc, FALSE, FALSE, time);
1350 return;
1351 }
1352 }
1353 cd_debug ("drop on %s (%.2f)", pPointedIcon?pPointedIcon->cName:"dock", fOrder);
1354
1355 gldi_container_notify_drop_data (CAIRO_CONTAINER (pDock), cReceivedData, pPointedIcon, fOrder);
1356
1357 gtk_drag_finish (dc, TRUE, FALSE, time);
1358 }
1359
1360 /*static gboolean _on_drag_drop (GtkWidget *pWidget, GdkDragContext *dc, gint x, gint y, guint time, G_GNUC_UNUSED CairoDock *pDock)
1361 {
1362 cd_message ("%s (%dx%d, %d)", __func__, x, y, time);
1363 GdkAtom target = gtk_drag_dest_find_target (pWidget, dc, NULL);
1364 gtk_drag_get_data (pWidget, dc, target, time);
1365 return TRUE; // in a drop zone.
1366 }*/
1367
1368
_on_drag_motion(GtkWidget * pWidget,GdkDragContext * dc,gint x,gint y,guint time,CairoDock * pDock)1369 static gboolean _on_drag_motion (GtkWidget *pWidget, GdkDragContext *dc, gint x, gint y, guint time, CairoDock *pDock)
1370 {
1371 cd_debug ("%s (%d;%d, %d)", __func__, x, y, time);
1372
1373 //\_________________ On simule les evenements souris habituels.
1374 if (! pDock->bIsDragging)
1375 {
1376 cd_debug ("start dragging");
1377 pDock->bIsDragging = TRUE;
1378
1379 /*GdkAtom gdkAtom = gdk_drag_get_selection (dc);
1380 Atom xAtom = gdk_x11_atom_to_xatom (gdkAtom);
1381 Window Xid = GDK_WINDOW_XID (dc->source_window);
1382 cd_debug (" <%s>", cairo_dock_get_property_name_on_xwindow (Xid, xAtom));*/
1383
1384 gboolean bStartAnimation = FALSE;
1385 gldi_object_notify (pDock, NOTIFICATION_START_DRAG_DATA, pDock, &bStartAnimation);
1386 if (bStartAnimation)
1387 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
1388
1389 /*pDock->iAvoidingMouseIconType = -1;
1390
1391 GdkAtom target = gtk_drag_dest_find_target (pWidget, dc, NULL);
1392 if (target == GDK_NONE)
1393 gdk_drag_status (dc, 0, time);
1394 else
1395 {
1396 gtk_drag_get_data (pWidget, dc, target, time);
1397 s_bWaitForData = TRUE;
1398 cd_debug ("get-data envoye\n");
1399 }*/
1400
1401 _on_enter_notify (pWidget, NULL, pDock); // ne sera effectif que la 1ere fois a chaque entree dans un dock.
1402 }
1403 else
1404 {
1405 //g_print ("move dragging\n");
1406 _on_motion_notify (pWidget, NULL, pDock);
1407 }
1408
1409 int X, Y;
1410 if (pDock->container.bIsHorizontal)
1411 {
1412 X = x - pDock->container.iWidth/2;
1413 Y = y;
1414 }
1415 else
1416 {
1417 Y = x;
1418 X = y - pDock->container.iWidth/2;
1419 }
1420 if (pDock->iInputState == CAIRO_DOCK_INPUT_AT_REST)
1421 {
1422 int w = pDock->iMinDockWidth;
1423 int h = pDock->iMinDockHeight;
1424
1425 if (X <= -w/2 || X >= w/2)
1426 return FALSE; // on n'accepte pas le drop.
1427 if (pDock->container.bDirectionUp)
1428 {
1429 if (Y < pDock->container.iHeight - h || Y >= pDock->container.iHeight)
1430 return FALSE; // on n'accepte pas le drop.
1431 }
1432 else
1433 {
1434 if (Y < 0 || Y > h)
1435 return FALSE; // on n'accepte pas le drop.
1436 }
1437 }
1438 else if (pDock->iInputState == CAIRO_DOCK_INPUT_HIDDEN)
1439 {
1440 return FALSE; // on n'accepte pas le drop.
1441 }
1442
1443 //g_print ("take the drop\n");
1444 gdk_drag_status (dc, GDK_ACTION_COPY, time);
1445 return TRUE; // on accepte le drop.
1446 }
1447
_on_drag_leave(GtkWidget * pWidget,G_GNUC_UNUSED GdkDragContext * dc,G_GNUC_UNUSED guint time,CairoDock * pDock)1448 void _on_drag_leave (GtkWidget *pWidget, G_GNUC_UNUSED GdkDragContext *dc, G_GNUC_UNUSED guint time, CairoDock *pDock)
1449 {
1450 //g_print ("stop dragging 1\n");
1451 Icon *icon = cairo_dock_get_pointed_icon (pDock->icons);
1452 if ((icon && icon->pSubDock) || pDock->iRefCount > 0) // on retarde l'evenement, car il arrive avant le leave-event, et donc le sous-dock se cache avant qu'on puisse y entrer.
1453 {
1454 cd_debug (">>> on attend...");
1455 while (gtk_events_pending ()) // on laisse le temps au signal d'entree dans le sous-dock d'etre traite, de facon a avoir un start-dragging avant de quitter cette fonction.
1456 gtk_main_iteration ();
1457 cd_debug (">>> pDock->container.bInside : %d", pDock->container.bInside);
1458 }
1459 //g_print ("stop dragging 2\n");
1460 s_bWaitForData = FALSE;
1461 pDock->bIsDragging = FALSE;
1462 s_bCouldDrop = pDock->bCanDrop;
1463 pDock->bCanDrop = FALSE;
1464 //cairo_dock_stop_marking_icons (pDock);
1465 pDock->iAvoidingMouseIconType = -1;
1466
1467 // emit a leave-event signal, since we don't get one if we leave the window too quickly (!)
1468 if (pDock->iSidLeaveDemand == 0)
1469 {
1470 pDock->iSidLeaveDemand = g_timeout_add (MAX (myDocksParam.iLeaveSubDockDelay, 330), (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pDock); // emit with a delay, so that we can leave and enter the dock for a few ms without making it hide.
1471 }
1472 // emulate a motion event so that the mouse position is up-to-date (which is not the case if we leave the window too quickly).
1473 _on_motion_notify (pWidget, NULL, pDock);
1474 }
1475
1476
1477 ///////////////////////
1478 /// CONTAINER IFACE ///
1479 ///////////////////////
1480
_cairo_dock_grow_up(CairoDock * pDock)1481 static gboolean _cairo_dock_grow_up (CairoDock *pDock)
1482 {
1483 //g_print ("%s (%d ; %2f ; bInside:%d)\n", __func__, pDock->iMagnitudeIndex, pDock->fFoldingFactor, pDock->container.bInside);
1484
1485 pDock->iMagnitudeIndex += myBackendsParam.iGrowUpInterval;
1486 if (pDock->iMagnitudeIndex > CAIRO_DOCK_NB_MAX_ITERATIONS)
1487 pDock->iMagnitudeIndex = CAIRO_DOCK_NB_MAX_ITERATIONS;
1488
1489 if (pDock->fFoldingFactor != 0)
1490 {
1491 int iAnimationDeltaT = cairo_dock_get_animation_delta_t (pDock);
1492 pDock->fFoldingFactor -= (double) iAnimationDeltaT / myBackendsParam.iUnfoldingDuration;
1493 if (pDock->fFoldingFactor < 0)
1494 pDock->fFoldingFactor = 0;
1495 }
1496
1497 gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock));
1498
1499 Icon *pLastPointedIcon = cairo_dock_get_pointed_icon (pDock->icons);
1500 Icon *pPointedIcon = cairo_dock_calculate_dock_icons (pDock);
1501 if (! pDock->bIsGrowingUp)
1502 return FALSE;
1503
1504 if (pLastPointedIcon != pPointedIcon && pDock->container.bInside)
1505 _on_change_icon (pLastPointedIcon, pPointedIcon, pDock); /// probablement inutile...
1506
1507 if (pDock->iMagnitudeIndex == CAIRO_DOCK_NB_MAX_ITERATIONS && pDock->fFoldingFactor == 0) // fin de grossissement et de depliage.
1508 {
1509 gldi_dialogs_replace_all ();
1510 return FALSE;
1511 }
1512 else
1513 return TRUE;
1514 }
1515
_hide_parent_dock(CairoDock * pDock)1516 static void _hide_parent_dock (CairoDock *pDock)
1517 {
1518 CairoDock *pParentDock = NULL;
1519 Icon *pIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pParentDock);
1520 if (pIcon && pParentDock)
1521 {
1522 if (pParentDock->iRefCount == 0)
1523 {
1524 cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pParentDock));
1525 }
1526 else
1527 {
1528 //cd_message ("on cache %s par parente", cDockName);
1529 gtk_widget_hide (pParentDock->container.pWidget);
1530 _hide_parent_dock (pParentDock);
1531 }
1532 }
1533 }
1534
_cairo_dock_shrink_down(CairoDock * pDock)1535 static gboolean _cairo_dock_shrink_down (CairoDock *pDock)
1536 {
1537 //g_print ("%s (%d, %f, %f)\n", __func__, pDock->iMagnitudeIndex, pDock->fFoldingFactor, pDock->fDecorationsOffsetX);
1538 //\_________________ On fait decroitre la magnitude du dock.
1539 pDock->iMagnitudeIndex -= myBackendsParam.iShrinkDownInterval;
1540 if (pDock->iMagnitudeIndex < 0)
1541 pDock->iMagnitudeIndex = 0;
1542
1543 //\_________________ On replie le dock.
1544 if (pDock->fFoldingFactor != 0 && pDock->fFoldingFactor != 1)
1545 {
1546 int iAnimationDeltaT = cairo_dock_get_animation_delta_t (pDock);
1547 pDock->fFoldingFactor += (double) iAnimationDeltaT / myBackendsParam.iUnfoldingDuration;
1548 if (pDock->fFoldingFactor > 1)
1549 pDock->fFoldingFactor = 1;
1550 }
1551
1552 //\_________________ On remet les decorations a l'equilibre.
1553 pDock->fDecorationsOffsetX *= .8;
1554 if (fabs (pDock->fDecorationsOffsetX) < 3)
1555 pDock->fDecorationsOffsetX = 0.;
1556
1557 //\_________________ On recupere la position de la souris manuellement (car a priori on est hors du dock).
1558 gldi_container_update_mouse_position (CAIRO_CONTAINER (pDock)); // ce n'est pas le motion_notify qui va nous donner des coordonnees en dehors du dock, et donc le fait d'etre dedans va nous faire interrompre le shrink_down et re-grossir, du coup il faut le faire ici. L'inconvenient, c'est que quand on sort par les cotes, il n'y a soudain plus d'icone pointee, et donc le dock devient tout plat subitement au lieu de le faire doucement. Heureusement j'ai trouve une astuce. ^_^
1559
1560 //\_________________ On recalcule les icones.
1561 ///if (iPrevMagnitudeIndex != 0)
1562 {
1563 cairo_dock_calculate_dock_icons (pDock);
1564 if (! pDock->bIsShrinkingDown)
1565 return FALSE;
1566 }
1567
1568 if (pDock->iMagnitudeIndex == 0 && (pDock->fFoldingFactor == 0 || pDock->fFoldingFactor == 1)) // on est arrive en bas.
1569 {
1570 //g_print ("equilibre atteint (%d)\n", pDock->container.bInside);
1571 if (! pDock->container.bInside) // on peut etre hors des icones sans etre hors de la fenetre.
1572 {
1573 //g_print ("rideau !\n");
1574
1575 //\__________________ On repasse derriere si on etait devant.
1576 if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && ! pDock->bIsBelow)
1577 cairo_dock_pop_down (pDock);
1578
1579 //\__________________ On se redimensionne en taille normale.
1580 if (! pDock->bAutoHide && pDock->iRefCount == 0/** && ! pDock->bMenuVisible*/) // fin de shrink sans auto-hide => taille normale.
1581 {
1582 //g_print ("taille normale (%x; %d)\n", pDock->pShapeBitmap , pDock->iInputState);
1583 if (pDock->pShapeBitmap && pDock->iInputState != CAIRO_DOCK_INPUT_AT_REST)
1584 {
1585 //g_print ("+++ input shape at rest on end shrinking\n");
1586 cairo_dock_set_input_shape_at_rest (pDock);
1587 pDock->iInputState = CAIRO_DOCK_INPUT_AT_REST;
1588 }
1589 }
1590
1591 //\__________________ On se cache si sous-dock.
1592 if (pDock->iRefCount > 0)
1593 {
1594 //g_print ("on cache ce sous-dock en sortant par lui\n");
1595 gtk_widget_hide (pDock->container.pWidget);
1596 _hide_parent_dock (pDock);
1597 }
1598 ///cairo_dock_hide_after_shortcut ();
1599 if (pDock->iVisibility == CAIRO_DOCK_VISI_SHORTKEY) // hide at the end of the shrink animation
1600 {
1601 gtk_widget_hide (pDock->container.pWidget);
1602 }
1603 }
1604 else
1605 {
1606 cairo_dock_calculate_dock_icons (pDock); // relance le grossissement si on est dedans.
1607 }
1608 if (!pDock->bIsGrowingUp)
1609 gldi_dialogs_replace_all ();
1610 return (!pDock->bIsGrowingUp && (pDock->fDecorationsOffsetX != 0 || (pDock->fFoldingFactor != 0 && pDock->fFoldingFactor != 1)));
1611 }
1612 else
1613 {
1614 return (!pDock->bIsGrowingUp);
1615 }
1616 }
1617
_cairo_dock_hide(CairoDock * pDock)1618 static gboolean _cairo_dock_hide (CairoDock *pDock)
1619 {
1620 //g_print ("%s (%d, %.2f, %.2f)\n", __func__, pDock->iMagnitudeIndex, pDock->fHideOffset, pDock->fPostHideOffset);
1621
1622 if (pDock->fHideOffset < 1) // the hiding animation is running.
1623 {
1624 pDock->fHideOffset += 1./myBackendsParam.iHideNbSteps;
1625 if (pDock->fHideOffset > .99) // fin d'anim.
1626 {
1627 pDock->fHideOffset = 1;
1628
1629 //g_print ("on arrete le cachage\n");
1630 gboolean bVisibleIconsPresent = FALSE;
1631 Icon *pIcon;
1632 GList *ic;
1633 for (ic = pDock->icons; ic != NULL; ic = ic->next)
1634 {
1635 pIcon = ic->data;
1636 if (pIcon->fInsertRemoveFactor != 0) // on accelere l'animation d'apparition/disparition.
1637 {
1638 if (pIcon->fInsertRemoveFactor > 0)
1639 pIcon->fInsertRemoveFactor = 0.05;
1640 else
1641 pIcon->fInsertRemoveFactor = - 0.05;
1642 }
1643
1644 if (! pIcon->bIsDemandingAttention && ! pIcon->bAlwaysVisible && ! pIcon->bIsLaunching)
1645 gldi_icon_stop_animation (pIcon); // s'il y'a une autre animation en cours, on l'arrete.
1646 else
1647 bVisibleIconsPresent = TRUE;
1648 }
1649
1650 pDock->pRenderer->calculate_icons (pDock);
1651 ///pDock->fFoldingFactor = (myBackendsParam.bAnimateOnAutoHide ? .99 : 0.); // on arme le depliage.
1652 cairo_dock_allow_entrance (pDock);
1653
1654 gldi_dialogs_replace_all ();
1655
1656 if (bVisibleIconsPresent) // il y'a des icones a montrer progressivement, on reste dans la boucle.
1657 {
1658 pDock->fPostHideOffset = 0.05;
1659 return TRUE;
1660 }
1661 else
1662 {
1663 pDock->fPostHideOffset = 1; // pour que les icones demandant l'attention plus tard soient visibles.
1664 return FALSE;
1665 }
1666 }
1667 }
1668 else if (pDock->fPostHideOffset > 0 && pDock->fPostHideOffset < 1) // the post-hiding animation is running.
1669 {
1670 pDock->fPostHideOffset += 1./myBackendsParam.iHideNbSteps;
1671 if (pDock->fPostHideOffset > .99)
1672 {
1673 pDock->fPostHideOffset = 1.;
1674 return FALSE;
1675 }
1676 }
1677 else // else no hiding animation is running.
1678 return FALSE;
1679 return TRUE;
1680 }
1681
_cairo_dock_show(CairoDock * pDock)1682 static gboolean _cairo_dock_show (CairoDock *pDock)
1683 {
1684 pDock->fHideOffset -= 1./myBackendsParam.iUnhideNbSteps;
1685 if (pDock->fHideOffset < 0.01)
1686 {
1687 pDock->fHideOffset = 0;
1688 cairo_dock_allow_entrance (pDock);
1689 gldi_dialogs_replace_all (); // we need it here so that a modal dialog is replaced when the dock unhides (else it would stay behind).
1690 return FALSE;
1691 }
1692 return TRUE;
1693 }
1694
_cairo_dock_handle_inserting_removing_icons(CairoDock * pDock)1695 static gboolean _cairo_dock_handle_inserting_removing_icons (CairoDock *pDock)
1696 {
1697 gboolean bRecalculateIcons = FALSE;
1698 GList* ic = pDock->icons, *next_ic;
1699 Icon *pIcon;
1700 while (ic != NULL)
1701 {
1702 pIcon = ic->data;
1703 if (pIcon->fInsertRemoveFactor == (gdouble)0.05) // end of removal animation -> the icon will be detached (at least)
1704 {
1705 GList *prev_ic = ic->prev;
1706 Icon *pPrevIcon = (prev_ic ? prev_ic->data : NULL);
1707 if (GLDI_OBJECT_IS_AUTO_SEPARATOR_ICON (pPrevIcon)) // this icon will maybe disappear with pIcon, so take the previous one
1708 prev_ic = prev_ic->prev;
1709
1710 gboolean bIsAppli = CAIRO_DOCK_IS_NORMAL_APPLI (pIcon);
1711 if (bIsAppli) // it's a valid appli icon that hides itself (for instance, because the window was unminimized with bHideVisibleApplis=true) => just detach it
1712 {
1713 cd_message ("cette appli (%s) est toujours valide, on la detache juste", pIcon->cName);
1714 pIcon->fInsertRemoveFactor = 0.; // on le fait avant le reload, sinon l'icone n'est pas rechargee.
1715 if (!pIcon->pAppli->bIsHidden && myTaskbarParam.bHideVisibleApplis) // on lui remet l'image normale qui servira d'embleme lorsque l'icone sera inseree a nouveau dans le dock.
1716 cairo_dock_reload_icon_image (pIcon, CAIRO_CONTAINER (pDock));
1717 pDock = gldi_appli_icon_detach (pIcon);
1718 if (pDock == NULL) // the dock has been destroyed (empty class sub-dock).
1719 {
1720 return FALSE;
1721 }
1722 }
1723 else
1724 {
1725 cd_message (" - %s va etre supprimee", pIcon->cName);
1726
1727 gldi_icon_detach (pIcon);
1728 if (pIcon->cClass != NULL && pDock == cairo_dock_get_class_subdock (pIcon->cClass)) // appli icon in its class sub-dock => destroy the class sub-dock if it becomes empty (we don't want an empty sub-dock).
1729 {
1730 gboolean bEmptyClassSubDock = cairo_dock_check_class_subdock_is_empty (pDock, pIcon->cClass);
1731 if (bEmptyClassSubDock)
1732 {
1733 gldi_object_unref (GLDI_OBJECT (pIcon));
1734 return FALSE;
1735 }
1736 }
1737
1738 gldi_object_delete (GLDI_OBJECT(pIcon));
1739 }
1740 next_ic = (prev_ic ? prev_ic->next : pDock->icons);
1741 }
1742 else
1743 {
1744 if (pIcon->fInsertRemoveFactor == (gdouble)-0.05) // end of appearance animation
1745 {
1746 pIcon->fInsertRemoveFactor = 0; // cela n'arrete pas l'animation, qui peut se poursuivre meme apres que l'icone ait atteint sa taille maximale.
1747 bRecalculateIcons = TRUE;
1748 }
1749 else if (pIcon->fInsertRemoveFactor != 0) // currently (dis)appearing
1750 {
1751 bRecalculateIcons = TRUE;
1752 }
1753 next_ic = ic->next;
1754 }
1755 ic = next_ic;
1756 }
1757
1758 if (bRecalculateIcons)
1759 cairo_dock_calculate_dock_icons (pDock);
1760 return TRUE;
1761 }
1762
_cairo_dock_dock_animation_loop(GldiContainer * pContainer)1763 static gboolean _cairo_dock_dock_animation_loop (GldiContainer *pContainer)
1764 {
1765 CairoDock *pDock = CAIRO_DOCK (pContainer);
1766 gboolean bContinue = FALSE;
1767 gboolean bUpdateSlowAnimation = FALSE;
1768 pContainer->iAnimationStep ++;
1769 if (pContainer->iAnimationStep * pContainer->iAnimationDeltaT >= CAIRO_DOCK_MIN_SLOW_DELTA_T)
1770 {
1771 bUpdateSlowAnimation = TRUE;
1772 pContainer->iAnimationStep = 0;
1773 pContainer->bKeepSlowAnimation = FALSE;
1774 }
1775
1776 if (pDock->bIsShrinkingDown)
1777 {
1778 pDock->bIsShrinkingDown = _cairo_dock_shrink_down (pDock);
1779 cairo_dock_redraw_container (CAIRO_CONTAINER (pDock));
1780 bContinue |= pDock->bIsShrinkingDown;
1781 }
1782 if (pDock->bIsGrowingUp)
1783 {
1784 pDock->bIsGrowingUp = _cairo_dock_grow_up (pDock);
1785 cairo_dock_redraw_container (CAIRO_CONTAINER (pDock));
1786 bContinue |= pDock->bIsGrowingUp;
1787 }
1788 if (pDock->bIsHiding)
1789 {
1790 //g_print ("le dock se cache\n");
1791 pDock->bIsHiding = _cairo_dock_hide (pDock);
1792 gtk_widget_queue_draw (pContainer->pWidget); // on n'utilise pas cairo_dock_redraw_container, sinon a la derniere iteration, le dock etant cache, la fonction ne le redessine pas.
1793 bContinue |= pDock->bIsHiding;
1794 }
1795 if (pDock->bIsShowing)
1796 {
1797 pDock->bIsShowing = _cairo_dock_show (pDock);
1798 cairo_dock_redraw_container (CAIRO_CONTAINER (pDock));
1799 bContinue |= pDock->bIsShowing;
1800 }
1801 //g_print (" => %d, %d\n", pDock->bIsShrinkingDown, pDock->bIsGrowingUp);
1802
1803 double fDockMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex);
1804 gboolean bIconIsAnimating;
1805 gboolean bNoMoreDemandingAttention = FALSE;
1806 Icon *icon;
1807 GList *ic;
1808 for (ic = pDock->icons; ic != NULL; ic = ic->next)
1809 {
1810 icon = ic->data;
1811
1812 icon->fDeltaYReflection = 0;
1813 if (myIconsParam.fAlphaAtRest != 1)
1814 icon->fAlpha = fDockMagnitude + myIconsParam.fAlphaAtRest * (1 - fDockMagnitude);
1815
1816 bIconIsAnimating = FALSE;
1817 if (bUpdateSlowAnimation)
1818 {
1819 gldi_object_notify (icon, NOTIFICATION_UPDATE_ICON_SLOW, icon, pDock, &bIconIsAnimating);
1820 pContainer->bKeepSlowAnimation |= bIconIsAnimating;
1821 }
1822 gldi_object_notify (icon, NOTIFICATION_UPDATE_ICON, icon, pDock, &bIconIsAnimating);
1823
1824 if ((icon->bIsDemandingAttention || icon->bAlwaysVisible) && cairo_dock_is_hidden (pDock)) // animation d'une icone demandant l'attention dans un dock cache => on force le dessin qui normalement ne se fait pas.
1825 {
1826 gtk_widget_queue_draw (pContainer->pWidget);
1827 }
1828
1829 bContinue |= bIconIsAnimating;
1830 if (! bIconIsAnimating)
1831 {
1832 icon->iAnimationState = CAIRO_DOCK_STATE_REST;
1833 if (icon->bIsDemandingAttention)
1834 {
1835 icon->bIsDemandingAttention = FALSE; // the attention animation has finished by itself after the time it was planned for.
1836 bNoMoreDemandingAttention = TRUE;
1837 }
1838 }
1839 }
1840 bContinue |= pContainer->bKeepSlowAnimation;
1841
1842 if (pDock->iVisibility == CAIRO_DOCK_VISI_KEEP_BELOW && bNoMoreDemandingAttention && ! pDock->bIsBelow && ! pContainer->bInside)
1843 {
1844 //g_print ("plus de raison d'etre devant\n");
1845 cairo_dock_pop_down (pDock);
1846 }
1847
1848 if (! _cairo_dock_handle_inserting_removing_icons (pDock))
1849 {
1850 cd_debug ("ce dock n'a plus de raison d'etre");
1851 return FALSE;
1852 }
1853
1854 if (bUpdateSlowAnimation)
1855 {
1856 gldi_object_notify (pDock, NOTIFICATION_UPDATE_SLOW, pDock, &pContainer->bKeepSlowAnimation);
1857 }
1858 gldi_object_notify (pDock, NOTIFICATION_UPDATE, pDock, &bContinue);
1859
1860 if (! bContinue && ! pContainer->bKeepSlowAnimation)
1861 {
1862 pContainer->iSidGLAnimation = 0;
1863 return FALSE;
1864 }
1865 else
1866 return TRUE;
1867 }
1868
1869 static gboolean _on_dock_destroyed (GtkWidget *menu, GldiContainer *pContainer);
_on_menu_deactivated(G_GNUC_UNUSED GtkMenuShell * menu,CairoDock * pDock)1870 static void _on_menu_deactivated (G_GNUC_UNUSED GtkMenuShell *menu, CairoDock *pDock)
1871 {
1872 //g_print ("\n+++ %s ()\n\n", __func__);
1873 g_return_if_fail (CAIRO_DOCK_IS_DOCK (pDock));
1874 if (pDock->bHasModalWindow) // don't send the signal if the menu was already deactivated.
1875 {
1876 pDock->bHasModalWindow = FALSE;
1877 cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));
1878 }
1879 }
_on_menu_destroyed(GtkWidget * menu,CairoDock * pDock)1880 static void _on_menu_destroyed (GtkWidget *menu, CairoDock *pDock)
1881 {
1882 //g_print ("\n+++ %s ()\n\n", __func__);
1883 gldi_object_remove_notification (pDock,
1884 NOTIFICATION_DESTROY,
1885 (GldiNotificationFunc) _on_dock_destroyed,
1886 menu);
1887 }
_on_dock_destroyed(GtkWidget * menu,GldiContainer * pContainer)1888 static gboolean _on_dock_destroyed (GtkWidget *menu, GldiContainer *pContainer)
1889 {
1890 //g_print ("\n+++ %s ()\n\n", __func__);
1891 g_signal_handlers_disconnect_matched
1892 (menu,
1893 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
1894 0,
1895 0,
1896 NULL,
1897 _on_menu_deactivated,
1898 pContainer);
1899 g_signal_handlers_disconnect_matched
1900 (menu,
1901 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
1902 0,
1903 0,
1904 NULL,
1905 _on_menu_destroyed,
1906 pContainer);
1907 return GLDI_NOTIFICATION_LET_PASS;
1908 }
_setup_menu(GldiContainer * pContainer,G_GNUC_UNUSED Icon * pIcon,GtkWidget * pMenu)1909 static void _setup_menu (GldiContainer *pContainer, G_GNUC_UNUSED Icon *pIcon, GtkWidget *pMenu)
1910 {
1911 // keep the dock visible
1912 CAIRO_DOCK (pContainer)->bHasModalWindow = TRUE;
1913
1914 // connect signals
1915 if (g_signal_handler_find (pMenu,
1916 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA,
1917 0,
1918 0,
1919 NULL,
1920 _on_menu_deactivated,
1921 pContainer) == 0) // on evite de connecter 2 fois ce signal, donc la fonction est appelable plusieurs fois sur un meme menu.
1922 {
1923 // when the menu is deactivated, hide the dock back if necessary.
1924 g_signal_connect (G_OBJECT (pMenu),
1925 "deactivate",
1926 G_CALLBACK (_on_menu_deactivated),
1927 pContainer);
1928 // when the menu is destroyed, remove the 'destroyed' notification on the dock.
1929 g_signal_connect (G_OBJECT (pMenu),
1930 "destroy",
1931 G_CALLBACK (_on_menu_destroyed),
1932 pContainer);
1933 // when the dock is destroyed, remove the 2 signals on the menu.
1934 gldi_object_register_notification (pContainer,
1935 NOTIFICATION_DESTROY,
1936 (GldiNotificationFunc) _on_dock_destroyed,
1937 GLDI_RUN_AFTER, pMenu); // the menu can stay alive even if the container disappear, so we need to ensure we won't call the callbacks then.
1938 }
1939 }
1940
_destroy_empty_dock(CairoDock * pDock)1941 static gboolean _destroy_empty_dock (CairoDock *pDock)
1942 {
1943 if (pDock->bIconIsFlyingAway) // keep the dock alive for now, in case the user re-inserts the flying icon in it.
1944 return TRUE;
1945 pDock->iSidDestroyEmptyDock = 0;
1946 if (pDock->icons == NULL && pDock->iRefCount == 0 && ! pDock->bIsMainDock) // le dock est toujours a detruire.
1947 {
1948 cd_debug ("The dock '%s' is empty. No icon, no dock.", pDock->cDockName);
1949 gldi_object_unref (GLDI_OBJECT(pDock));
1950 }
1951 return FALSE;
1952 }
_detach_icon(GldiContainer * pContainer,Icon * icon)1953 static void _detach_icon (GldiContainer *pContainer, Icon *icon)
1954 {
1955 CairoDock *pDock = CAIRO_DOCK (pContainer);
1956 cd_debug ("%s (%s)", __func__, icon->cName);
1957
1958 //\___________________ On trouve l'icone et ses 2 voisins.
1959 GList *prev_ic = NULL, *ic, *next_ic;
1960 Icon *pPrevIcon = NULL, *pNextIcon = NULL;
1961 for (ic = pDock->icons; ic != NULL; ic = ic->next)
1962 {
1963 if (ic->data == icon)
1964 {
1965 prev_ic = ic->prev;
1966 next_ic = ic->next;
1967 if (prev_ic)
1968 pPrevIcon = prev_ic->data;
1969 if (next_ic)
1970 pNextIcon = next_ic->data;
1971 break;
1972 }
1973 }
1974 g_return_if_fail (ic != NULL); // not found (shouldn't happen)
1975
1976 //\___________________ On stoppe ses animations.
1977 gldi_icon_stop_animation (icon);
1978
1979 //\___________________ On desactive sa miniature.
1980 if (icon->pAppli != NULL)
1981 {
1982 //cd_debug ("on desactive la miniature de %s (Xid : %lx)", icon->cName, icon->Xid);
1983 gldi_window_set_thumbnail_area (icon->pAppli, 0, 0, 0, 0);
1984 }
1985
1986 //\___________________ On l'enleve de la liste.
1987 pDock->icons = g_list_delete_link (pDock->icons, ic);
1988 ic = NULL;
1989 pDock->fFlatDockWidth -= icon->fWidth + myIconsParam.iIconGap;
1990
1991 //\___________________ On enleve le separateur si c'est la derniere icone de son type.
1992 if (! CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (icon))
1993 {
1994 if ((pPrevIcon == NULL || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pPrevIcon)) && CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (pNextIcon))
1995 {
1996 pDock->icons = g_list_delete_link (pDock->icons, next_ic); // optimisation
1997 next_ic = NULL;
1998 pDock->fFlatDockWidth -= pNextIcon->fWidth + myIconsParam.iIconGap;
1999 cairo_dock_set_icon_container (pNextIcon, NULL);
2000 gldi_object_unref (GLDI_OBJECT (pNextIcon));
2001 pNextIcon = NULL;
2002 }
2003 if ((pNextIcon == NULL || CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pNextIcon)) && CAIRO_DOCK_IS_AUTOMATIC_SEPARATOR (pPrevIcon))
2004 {
2005 pDock->icons = g_list_delete_link (pDock->icons, prev_ic); // optimisation
2006 prev_ic = NULL;
2007 pDock->fFlatDockWidth -= pPrevIcon->fWidth + myIconsParam.iIconGap;
2008 cairo_dock_set_icon_container (pPrevIcon, NULL);
2009 gldi_object_unref (GLDI_OBJECT (pPrevIcon));
2010 pPrevIcon = NULL;
2011 }
2012 }
2013
2014 //\___________________ Cette icone realisait peut-etre le max des hauteurs, comme on l'enleve on recalcule ce max.
2015 Icon *pOtherIcon;
2016 if (icon->fHeight >= pDock->iMaxIconHeight)
2017 {
2018 pDock->iMaxIconHeight = 0;
2019 for (ic = pDock->icons; ic != NULL; ic = ic->next)
2020 {
2021 pOtherIcon = ic->data;
2022 if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pOtherIcon))
2023 {
2024 pDock->iMaxIconHeight = MAX (pDock->iMaxIconHeight, pOtherIcon->fHeight);
2025 if (pOtherIcon->fHeight == icon->fHeight) // on sait qu'on n'ira pas plus haut.
2026 break;
2027 }
2028 }
2029 }
2030
2031 //\___________________ On la remet a la taille normale en vue d'une reinsertion quelque part.
2032 icon->fWidth /= pDock->container.fRatio;
2033 icon->fHeight /= pDock->container.fRatio;
2034
2035 //\___________________ On prevoit le redessin de l'icone pointant sur le sous-dock.
2036 if (pDock->iRefCount != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
2037 {
2038 cairo_dock_trigger_redraw_subdock_content (pDock);
2039 }
2040
2041 //\___________________ On prevoit la destruction du dock si c'est un dock principal qui devient vide.
2042 if (pDock->iRefCount == 0 && pDock->icons == NULL && ! pDock->bIsMainDock) // on supprime les docks principaux vides.
2043 {
2044 if (pDock->iSidDestroyEmptyDock == 0)
2045 pDock->iSidDestroyEmptyDock = g_idle_add ((GSourceFunc) _destroy_empty_dock, pDock);
2046 }
2047 else
2048 {
2049 cairo_dock_trigger_update_dock_size (pDock);
2050 }
2051
2052 //\___________________ Notify everybody.
2053 icon->fInsertRemoveFactor = 0.;
2054 gldi_object_notify (pDock, NOTIFICATION_REMOVE_ICON, icon, pDock);
2055
2056 //\___________________ unset the container, now that it's completely detached from it.
2057 g_free (icon->cParentDockName);
2058 icon->cParentDockName = NULL;
2059 }
2060
_insert_icon(GldiContainer * pContainer,Icon * icon,gboolean bAnimateIcon)2061 static void _insert_icon (GldiContainer *pContainer, Icon *icon, gboolean bAnimateIcon)
2062 {
2063 CairoDock *pDock = CAIRO_DOCK (pContainer);
2064
2065 cd_debug ("insert %s in %s", icon->cName, gldi_dock_get_name (pDock));
2066
2067 if (icon->cParentDockName == NULL)
2068 icon->cParentDockName = g_strdup (gldi_dock_get_name (pDock));
2069
2070 //\______________ check if a separator is needed (ie, if the group of the new icon (not its order) is new).
2071 gboolean bSeparatorNeeded = FALSE;
2072 if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
2073 {
2074 Icon *pSameTypeIcon = cairo_dock_get_first_icon_of_group (pDock->icons, icon->iGroup);
2075 if (pSameTypeIcon == NULL && pDock->icons != NULL)
2076 {
2077 bSeparatorNeeded = TRUE;
2078 }
2079 }
2080
2081 //\______________ insert the icon in the list.
2082 if (icon->fOrder == CAIRO_DOCK_LAST_ORDER)
2083 {
2084 Icon *pLastIcon = cairo_dock_get_last_icon_of_order (pDock->icons, icon->iGroup);
2085 if (pLastIcon != NULL)
2086 icon->fOrder = pLastIcon->fOrder + 1;
2087 else
2088 icon->fOrder = 1;
2089 }
2090
2091 pDock->icons = g_list_insert_sorted (pDock->icons,
2092 icon,
2093 (GCompareFunc)cairo_dock_compare_icons_order);
2094
2095 //\______________ set the icon size, now that it's inside a container.
2096 int wi = icon->image.iWidth, hi = icon->image.iHeight;
2097 cairo_dock_set_icon_size_in_dock (pDock, icon);
2098
2099 if (wi != cairo_dock_icon_get_allocated_width (icon) || hi != cairo_dock_icon_get_allocated_height (icon) // if size has changed, reload the buffers
2100 || (! icon->image.pSurface && ! icon->image.iTexture)) // might happen, for instance if the icon is a launcher pinned on a desktop and was detached before being loaded.
2101 cairo_dock_trigger_load_icon_buffers (icon);
2102
2103 pDock->fFlatDockWidth += myIconsParam.iIconGap + icon->fWidth;
2104 if (! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon))
2105 pDock->iMaxIconHeight = MAX (pDock->iMaxIconHeight, icon->fHeight);
2106
2107 //\______________ insert a separator if needed.
2108 if (bSeparatorNeeded)
2109 {
2110 // insert a separator after if needed
2111 Icon *pNextIcon = cairo_dock_get_next_icon (pDock->icons, icon);
2112 if (pNextIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pNextIcon))
2113 {
2114 Icon *pSeparatorIcon = gldi_auto_separator_icon_new (icon, pNextIcon);
2115 gldi_icon_insert_in_container (pSeparatorIcon, CAIRO_CONTAINER(pDock), ! CAIRO_DOCK_ANIMATE_ICON);
2116 }
2117
2118 // insert a separator before if needed
2119 Icon *pPrevIcon = cairo_dock_get_previous_icon (pDock->icons, icon);
2120 if (pPrevIcon != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pPrevIcon))
2121 {
2122 Icon *pSeparatorIcon = gldi_auto_separator_icon_new (pPrevIcon, icon);
2123 gldi_icon_insert_in_container (pSeparatorIcon, CAIRO_CONTAINER(pDock), ! CAIRO_DOCK_ANIMATE_ICON);
2124 }
2125 }
2126
2127 //\______________ On effectue les actions demandees.
2128 if (bAnimateIcon)
2129 {
2130 if (cairo_dock_animation_will_be_visible (pDock))
2131 icon->fInsertRemoveFactor = - 0.95;
2132 else
2133 icon->fInsertRemoveFactor = - 0.05;
2134 cairo_dock_launch_animation (CAIRO_CONTAINER (pDock));
2135 }
2136 else
2137 icon->fInsertRemoveFactor = 0.;
2138
2139 cairo_dock_trigger_update_dock_size (pDock);
2140
2141 if (pDock->iRefCount != 0 && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon)) // on prevoit le redessin de l'icone pointant sur le sous-dock.
2142 {
2143 cairo_dock_trigger_redraw_subdock_content (pDock);
2144 }
2145
2146 if (icon->pSubDock != NULL)
2147 gldi_subdock_synchronize_orientation (icon->pSubDock, pDock, FALSE);
2148
2149 //\______________ Notify everybody.
2150 gldi_object_notify (pDock, NOTIFICATION_INSERT_ICON, icon, pDock); /// TODO: make it a Container notification...
2151 }
2152
gldi_dock_init_internals(CairoDock * pDock)2153 void gldi_dock_init_internals (CairoDock *pDock)
2154 {
2155 pDock->container.iface.animation_loop = _cairo_dock_dock_animation_loop;
2156 pDock->container.iface.setup_menu = _setup_menu;
2157 pDock->container.iface.detach_icon = _detach_icon;
2158 pDock->container.iface.insert_icon = _insert_icon;
2159
2160 //\__________________ set up its window
2161 GtkWidget *pWindow = pDock->container.pWidget;
2162 gtk_container_set_border_width (GTK_CONTAINER (pWindow), 0);
2163 gtk_window_set_gravity (GTK_WINDOW (pWindow), GDK_GRAVITY_STATIC);
2164 gtk_window_set_type_hint (GTK_WINDOW (pWindow), GDK_WINDOW_TYPE_HINT_DOCK); // window must not be mapped
2165
2166 //\__________________ connect to events.
2167 gtk_widget_add_events (pWindow,
2168 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK |
2169 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
2170 GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);
2171
2172 g_signal_connect (G_OBJECT (pWindow),
2173 "draw",
2174 G_CALLBACK (_on_expose),
2175 pDock);
2176 g_signal_connect (G_OBJECT (pWindow),
2177 "configure-event",
2178 G_CALLBACK (_on_configure),
2179 pDock);
2180 g_signal_connect (G_OBJECT (pWindow),
2181 "key-release-event",
2182 G_CALLBACK (_on_key_release),
2183 pDock);
2184 g_signal_connect (G_OBJECT (pWindow),
2185 "key-press-event",
2186 G_CALLBACK (_on_key_release),
2187 pDock);
2188 g_signal_connect (G_OBJECT (pWindow),
2189 "button-press-event",
2190 G_CALLBACK (_on_button_press),
2191 pDock);
2192 g_signal_connect (G_OBJECT (pWindow),
2193 "button-release-event",
2194 G_CALLBACK (_on_button_press),
2195 pDock);
2196 g_signal_connect (G_OBJECT (pWindow),
2197 "scroll-event",
2198 G_CALLBACK (_on_scroll),
2199 pDock);
2200 g_signal_connect (G_OBJECT (pWindow),
2201 "motion-notify-event",
2202 G_CALLBACK (_on_motion_notify),
2203 pDock);
2204 g_signal_connect (G_OBJECT (pWindow),
2205 "enter-notify-event",
2206 G_CALLBACK (_on_enter_notify),
2207 pDock);
2208 g_signal_connect (G_OBJECT (pWindow),
2209 "leave-notify-event",
2210 G_CALLBACK (_on_leave_notify),
2211 pDock);
2212 gldi_container_enable_drop (CAIRO_CONTAINER (pDock),
2213 G_CALLBACK (_on_drag_data_received),
2214 pDock);
2215 g_signal_connect (G_OBJECT (pWindow),
2216 "drag-motion",
2217 G_CALLBACK (_on_drag_motion),
2218 pDock);
2219 g_signal_connect (G_OBJECT (pWindow),
2220 "drag-leave",
2221 G_CALLBACK (_on_drag_leave),
2222 pDock);
2223 /*g_signal_connect (G_OBJECT (pWindow),
2224 "drag-drop",
2225 G_CALLBACK (_on_drag_drop),
2226 pDock);*/
2227
2228 gtk_widget_show_all (pDock->container.pWidget);
2229 }
2230
2231
2232 ///////////////
2233 /// FACTORY ///
2234 ///////////////
2235
gldi_dock_new(const gchar * cDockName)2236 CairoDock *gldi_dock_new (const gchar *cDockName)
2237 {
2238 CairoDockAttr attr;
2239 memset (&attr, 0, sizeof (CairoDockAttr));
2240 attr.cDockName = cDockName;
2241 return (CairoDock*)gldi_object_new (&myDockObjectMgr, &attr);
2242 }
2243
gldi_subdock_new(const gchar * cDockName,const gchar * cRendererName,CairoDock * pParentDock,GList * pIconList)2244 CairoDock *gldi_subdock_new (const gchar *cDockName, const gchar *cRendererName, CairoDock *pParentDock, GList *pIconList)
2245 {
2246 CairoDockAttr attr;
2247 memset (&attr, 0, sizeof (CairoDockAttr));
2248 attr.bSubDock = TRUE;
2249 attr.cDockName = cDockName;
2250 attr.cRendererName = cRendererName;
2251 attr.pParentDock = pParentDock;
2252 attr.pIconList = pIconList;
2253 return (CairoDock*)gldi_object_new (&myDockObjectMgr, &attr);
2254 }
2255
2256
cairo_dock_remove_icons_from_dock(CairoDock * pDock,CairoDock * pReceivingDock)2257 void cairo_dock_remove_icons_from_dock (CairoDock *pDock, CairoDock *pReceivingDock)
2258 {
2259 g_return_if_fail (pReceivingDock != NULL);
2260 GList *pIconsList = pDock->icons;
2261 pDock->icons = NULL;
2262 Icon *icon;
2263 GList *ic;
2264 for (ic = pIconsList; ic != NULL; ic = ic->next)
2265 {
2266 icon = ic->data;
2267
2268 cairo_dock_set_icon_container (icon, NULL); // manually detach the icon
2269
2270 gldi_theme_icon_write_container_name_in_conf_file (icon, pReceivingDock->cDockName);
2271
2272 cd_debug (" on re-attribue %s au dock %s", icon->cName, pReceivingDock->cDockName);
2273 gldi_icon_insert_in_container (icon, CAIRO_CONTAINER(pReceivingDock), CAIRO_DOCK_ANIMATE_ICON);
2274
2275 if (CAIRO_DOCK_IS_APPLET (icon))
2276 {
2277 icon->pModuleInstance->pContainer = CAIRO_CONTAINER (pReceivingDock); // astuce pour ne pas avoir a recharger le fichier de conf ^_^
2278 icon->pModuleInstance->pDock = pReceivingDock;
2279 gldi_object_reload (GLDI_OBJECT(icon->pModuleInstance), FALSE);
2280 }
2281 else if (cairo_dock_get_icon_data_renderer (icon) != NULL)
2282 cairo_dock_reload_data_renderer_on_icon (icon, CAIRO_CONTAINER (pReceivingDock));
2283 }
2284
2285 g_list_free (pIconsList);
2286 }
2287
2288
cairo_dock_reload_buffers_in_dock(CairoDock * pDock,gboolean bRecursive,gboolean bUpdateIconSize)2289 void cairo_dock_reload_buffers_in_dock (CairoDock *pDock, gboolean bRecursive, gboolean bUpdateIconSize)
2290 {
2291 //g_print ("************%s (%d, %d)\n", __func__, pDock->bIsMainDock, bRecursive);
2292 if (bUpdateIconSize && pDock->bGlobalIconSize)
2293 pDock->iIconSize = myIconsParam.iIconWidth;
2294
2295 // for each icon, reload its buffer (size may change).
2296 Icon* icon;
2297 GList* ic;
2298 for (ic = pDock->icons; ic != NULL; ic = ic->next)
2299 {
2300 icon = ic->data;
2301
2302 if (CAIRO_DOCK_IS_APPLET (icon)) // for an applet, we need to let the module know that the size or the theme has changed, so that it can reload its private buffers.
2303 {
2304 gldi_object_reload (GLDI_OBJECT(icon->pModuleInstance), FALSE);
2305 }
2306 else
2307 {
2308 if (bUpdateIconSize)
2309 {
2310 cairo_dock_icon_set_requested_size (icon, 0, 0);
2311 cairo_dock_set_icon_size_in_dock (pDock, icon);
2312 }
2313
2314 if (bUpdateIconSize && cairo_dock_get_icon_data_renderer (icon) != NULL) // we need to reload the DataRenderer to use the new size
2315 {
2316 cairo_dock_load_icon_buffers (icon, CAIRO_CONTAINER (pDock)); // the DataRenderer uses the ImageBuffer's size on loading, so we need to load it now
2317 cairo_dock_reload_data_renderer_on_icon (icon, CAIRO_CONTAINER (pDock));
2318 }
2319 else
2320 {
2321 cairo_dock_trigger_load_icon_buffers (icon);
2322 }
2323 }
2324
2325 if (bRecursive && icon->pSubDock != NULL) // we handle the sub-dock for applets too, so that they don't need to care.
2326 {
2327 if (bUpdateIconSize)
2328 icon->pSubDock->iIconSize = pDock->iIconSize;
2329 cairo_dock_reload_buffers_in_dock (icon->pSubDock, bRecursive, bUpdateIconSize);
2330 }
2331 }
2332
2333 if (bUpdateIconSize)
2334 {
2335 cairo_dock_update_dock_size (pDock);
2336 }
2337 gtk_widget_queue_draw (pDock->container.pWidget);
2338 }
2339
2340
cairo_dock_set_icon_size_in_dock(CairoDock * pDock,Icon * icon)2341 void cairo_dock_set_icon_size_in_dock (CairoDock *pDock, Icon *icon)
2342 {
2343 if (pDock->pRenderer && pDock->pRenderer->set_icon_size) // the view wants to decide the icons size.
2344 {
2345 pDock->pRenderer->set_icon_size (icon, pDock);
2346 }
2347 else // generic method: icon extent = base size * max zoom
2348 {
2349 int wi, hi; // icon size (icon size displayed at rest, as defined in the config)
2350 int wa, ha; // allocated size (surface/texture).
2351 gboolean bIsHorizontal = (pDock->container.bIsHorizontal || (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon) && myIconsParam.bRevolveSeparator));
2352
2353 // get the displayed icon size as defined in the config
2354 if (! pDock->bGlobalIconSize && pDock->iIconSize != 0)
2355 {
2356 wi = hi = pDock->iIconSize;
2357 }
2358 else // same size as main dock.
2359 {
2360 wi = myIconsParam.iIconWidth;
2361 hi = myIconsParam.iIconHeight;
2362 }
2363
2364 if (CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (icon)) // separators have their own size.
2365 {
2366 wi = myIconsParam.iSeparatorWidth;
2367 hi = MIN (myIconsParam.iSeparatorHeight, hi);
2368 }
2369
2370 // take into account the requested displayed size if any
2371 int wir = cairo_dock_icon_get_requested_display_width (icon);
2372 if (wir != 0)
2373 wi = wir;
2374 int hir = cairo_dock_icon_get_requested_display_height (icon);
2375 if (hir != 0)
2376 hi = MIN (hir, hi); // limit the icon height to the default height.
2377
2378 // get the requested size if any
2379 wa = cairo_dock_icon_get_requested_width (icon);
2380 ha = cairo_dock_icon_get_requested_height (icon);
2381
2382 // compute the missing size (allocated or displayed).
2383 double fMaxScale = 1 + myIconsParam.fAmplitude;
2384 if (wa == 0)
2385 {
2386 wa = (bIsHorizontal ? wi : hi) * fMaxScale;
2387 }
2388 else
2389 {
2390 if (bIsHorizontal)
2391 wi = wa / fMaxScale;
2392 else
2393 hi = wa / fMaxScale;
2394 }
2395 if (ha == 0)
2396 {
2397 ha = (bIsHorizontal ? hi : wi) * fMaxScale;
2398 }
2399 else
2400 {
2401 if (bIsHorizontal)
2402 hi = ha / fMaxScale;
2403 else
2404 wi = ha / fMaxScale;
2405 }
2406
2407 // set both allocated and displayed size
2408 cairo_dock_icon_set_allocated_size (icon, wa, ha);
2409 icon->fWidth = wi;
2410 icon->fHeight = hi;
2411 }
2412 // take into account the current ratio
2413 icon->fWidth *= pDock->container.fRatio;
2414 icon->fHeight *= pDock->container.fRatio;
2415 }
2416
2417
cairo_dock_create_redirect_texture_for_dock(CairoDock * pDock)2418 void cairo_dock_create_redirect_texture_for_dock (CairoDock *pDock)
2419 {
2420 if (! g_openglConfig.bFboAvailable)
2421 return ;
2422 if (pDock->iRedirectedTexture == 0)
2423 {
2424 pDock->iRedirectedTexture = cairo_dock_create_texture_from_raw_data (NULL,
2425 (pDock->container.bIsHorizontal ? pDock->container.iWidth : pDock->container.iHeight),
2426 (pDock->container.bIsHorizontal ? pDock->container.iHeight : pDock->container.iWidth));
2427 }
2428 if (pDock->iFboId == 0)
2429 glGenFramebuffersEXT(1, &pDock->iFboId);
2430 }
2431