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 <gtk/gtk.h>
22
23 #include "cairo-dock-applications-manager.h" // cairo_dock_set_icons_geometry_for_window_manager
24 #include "cairo-dock-launcher-manager.h"
25 #include "cairo-dock-separator-manager.h" // GLDI_OBJECT_IS_SEPARATOR_ICON
26 #include "cairo-dock-stack-icon-manager.h" // GLDI_OBJECT_IS_DRAWER_ICON
27 #include "cairo-dock-class-icon-manager.h"
28 #include "cairo-dock-icon-facility.h"
29 #include "cairo-dock-backends-manager.h" // myBackendsParam.fSubDockSizeRatio
30 #include "cairo-dock-log.h"
31 #include "cairo-dock-style-manager.h"
32 #include "cairo-dock-dock-manager.h"
33 #include "cairo-dock-dialog-manager.h" // gldi_dialogs_replace_all
34 #include "cairo-dock-indicator-manager.h" // myIndicators.bUseClassIndic
35 #include "cairo-dock-animations.h"
36 #include "cairo-dock-desktop-manager.h" // gldi_desktop_get*
37 #include "cairo-dock-data-renderer.h" // cairo_dock_reload_data_renderer_on_icon
38 #include "cairo-dock-opengl.h" // gldi_gl_container_begin_draw
39
40 extern CairoDockGLConfig g_openglConfig;
41 #include "cairo-dock-dock-facility.h"
42
43 extern gboolean g_bUseOpenGL; // for cairo_dock_make_preview()
44
45
46 /**
47 * @pre iMaxIconHeight and fFlatDockWidth have to have been updated
48 */
cairo_dock_update_dock_size(CairoDock * pDock)49 void cairo_dock_update_dock_size (CairoDock *pDock)
50 {
51 g_return_if_fail (pDock != NULL);
52 //g_print ("%s (%p, %d)\n", __func__, pDock, pDock->iRefCount);
53 if (pDock->iSidUpdateDockSize != 0)
54 {
55 //g_print (" -> delayed\n");
56 return;
57 }
58 int iPrevMaxDockHeight = pDock->iMaxDockHeight;
59 int iPrevMaxDockWidth = pDock->iMaxDockWidth;
60
61 //\__________________________ First compute the dock's size.
62
63 // set the icons' size back to their default, otherwise max_dock_size could be wrong
64 if (pDock->container.fRatio != 0)
65 {
66 GList *ic;
67 Icon *icon;
68 pDock->fFlatDockWidth = -myIconsParam.iIconGap;
69 pDock->iMaxIconHeight = 0;
70 for (ic = pDock->icons; ic != NULL; ic = ic->next)
71 {
72 icon = ic->data;
73 icon->fWidth /= pDock->container.fRatio;
74 icon->fHeight /= pDock->container.fRatio;
75 pDock->fFlatDockWidth += icon->fWidth + myIconsParam.iIconGap;
76 if (! GLDI_OBJECT_IS_SEPARATOR_ICON (icon))
77 pDock->iMaxIconHeight = MAX (pDock->iMaxIconHeight, icon->fHeight);
78 }
79 if (pDock->iMaxIconHeight == 0)
80 pDock->iMaxIconHeight = 10;
81 pDock->container.fRatio = 1.;
82 }
83
84 // compute the size of the dock.
85 pDock->iActiveWidth = pDock->iActiveHeight = 0;
86 pDock->pRenderer->compute_size (pDock);
87 if (pDock->iActiveWidth == 0)
88 pDock->iActiveWidth = pDock->iMaxDockWidth;
89 if (pDock->iActiveHeight == 0)
90 pDock->iActiveHeight = pDock->iMaxDockHeight;
91
92 // in case it's larger than the screen, iterate on the ratio until it fits the screen's width
93 int iScreenHeight = gldi_dock_get_screen_height (pDock);
94 double hmax = pDock->iMaxIconHeight;
95 int iMaxAuthorizedWidth = cairo_dock_get_max_authorized_dock_width (pDock);
96 int n = 0; // counter to ensure we'll not loop forever.
97 do
98 {
99 double fPrevRatio = pDock->container.fRatio;
100 //g_print (" %s (%d / %d)\n", __func__, (int)pDock->iMaxDockWidth, iMaxAuthorizedWidth);
101 if (pDock->iMaxDockWidth > iMaxAuthorizedWidth)
102 {
103 pDock->container.fRatio *= (double)iMaxAuthorizedWidth / pDock->iMaxDockWidth;
104 }
105 else
106 {
107 double fMaxRatio = (pDock->iRefCount == 0 ? 1 : myBackendsParam.fSubDockSizeRatio);
108 if (pDock->container.fRatio < fMaxRatio)
109 {
110 pDock->container.fRatio *= (double)iMaxAuthorizedWidth / pDock->iMaxDockWidth;
111 pDock->container.fRatio = MIN (pDock->container.fRatio, fMaxRatio);
112 }
113 else
114 pDock->container.fRatio = fMaxRatio;
115 }
116
117 if (pDock->iMaxDockHeight > iScreenHeight)
118 {
119 pDock->container.fRatio = MIN (pDock->container.fRatio, fPrevRatio * iScreenHeight / pDock->iMaxDockHeight);
120 }
121
122 if (fPrevRatio != pDock->container.fRatio)
123 {
124 //g_print (" -> change of the ratio : %.3f -> %.3f (%d, %d try)\n", fPrevRatio, pDock->container.fRatio, pDock->iRefCount, n);
125 Icon *icon;
126 GList *ic;
127 pDock->fFlatDockWidth = -myIconsParam.iIconGap;
128 for (ic = pDock->icons; ic != NULL; ic = ic->next)
129 {
130 icon = ic->data;
131 icon->fWidth *= pDock->container.fRatio / fPrevRatio;
132 icon->fHeight *= pDock->container.fRatio / fPrevRatio;
133 pDock->fFlatDockWidth += icon->fWidth + myIconsParam.iIconGap;
134 }
135 hmax *= pDock->container.fRatio / fPrevRatio;
136
137 pDock->iActiveWidth = pDock->iActiveHeight = 0;
138 pDock->pRenderer->compute_size (pDock);
139 if (pDock->iActiveWidth == 0)
140 pDock->iActiveWidth = pDock->iMaxDockWidth;
141 if (pDock->iActiveHeight == 0)
142 pDock->iActiveHeight = pDock->iMaxDockHeight;
143 }
144
145 //g_print ("*** ratio : %.3f -> %.3f\n", fPrevRatio, pDock->container.fRatio);
146 n ++;
147 } while ((pDock->iMaxDockWidth > iMaxAuthorizedWidth || pDock->iMaxDockHeight > iScreenHeight || (pDock->container.fRatio < 1 && pDock->iMaxDockWidth < iMaxAuthorizedWidth-5)) && n < 8);
148 pDock->iMaxIconHeight = hmax;
149 //g_print (">>> iMaxIconHeight : %d, ratio : %.2f, fFlatDockWidth : %.2f\n", (int) pDock->iMaxIconHeight, pDock->container.fRatio, pDock->fFlatDockWidth);
150
151 //\__________________________ Then take the necessary actions due to the new size.
152 // calculate the position of icons in the new frame.
153 cairo_dock_calculate_dock_icons (pDock);
154
155 // update the dock's shape.
156 if (iPrevMaxDockHeight == pDock->iMaxDockHeight && iPrevMaxDockWidth == pDock->iMaxDockWidth) // if the size has changed, shapes will be updated by the "configure" callback, so we don't need to do it here; if not, we do it in case the icons define a new shape (ex.: separators in Panel view) or in case the screen edge has changed.
157 {
158 cairo_dock_update_input_shape (pDock); // done after the icons' position is known.
159 switch (pDock->iInputState) // update the input zone
160 {
161 case CAIRO_DOCK_INPUT_ACTIVE: cairo_dock_set_input_shape_active (pDock); break;
162 case CAIRO_DOCK_INPUT_AT_REST: cairo_dock_set_input_shape_at_rest (pDock); break;
163 default: break; // if hidden, nothing to do.
164 }
165 }
166
167 if (iPrevMaxDockHeight == pDock->iMaxDockHeight && iPrevMaxDockWidth == pDock->iMaxDockWidth) // same remark as for the input shape.
168 {
169 /// TODO: check that...
170 ///pDock->bWMIconsNeedUpdate = TRUE;
171 cairo_dock_trigger_set_WM_icons_geometry (pDock);
172 }
173
174 // if the size has changed, move the dock to keep it centered.
175 if (gldi_container_is_visible (CAIRO_CONTAINER (pDock)) && (iPrevMaxDockHeight != pDock->iMaxDockHeight || iPrevMaxDockWidth != pDock->iMaxDockWidth))
176 {
177 //g_print ("*******%s (%dx%d -> %dx%d)\n", __func__, iPrevMaxDockWidth, iPrevMaxDockHeight, pDock->iMaxDockWidth, pDock->iMaxDockHeight);
178 cairo_dock_move_resize_dock (pDock);
179 }
180
181 // reload its background.
182 cairo_dock_trigger_load_dock_background (pDock);
183
184 // update the space reserved on the screen.
185 if (pDock->iRefCount == 0 && pDock->iVisibility == CAIRO_DOCK_VISI_RESERVE)
186 cairo_dock_reserve_space_for_dock (pDock, TRUE);
187 }
188
_update_dock_size_idle(CairoDock * pDock)189 static gboolean _update_dock_size_idle (CairoDock *pDock)
190 {
191 pDock->iSidUpdateDockSize = 0;
192 cairo_dock_update_dock_size (pDock);
193 gtk_widget_queue_draw (pDock->container.pWidget);
194 return FALSE;
195 }
cairo_dock_trigger_update_dock_size(CairoDock * pDock)196 void cairo_dock_trigger_update_dock_size (CairoDock *pDock)
197 {
198 if (pDock->iSidUpdateDockSize == 0)
199 {
200 pDock->iSidUpdateDockSize = g_idle_add ((GSourceFunc) _update_dock_size_idle, pDock);
201 }
202 }
203
_emit_leave_signal_delayed(CairoDock * pDock)204 static gboolean _emit_leave_signal_delayed (CairoDock *pDock)
205 {
206 cairo_dock_emit_leave_signal (CAIRO_CONTAINER (pDock));
207 pDock->iSidLeaveDemand = 0;
208 return FALSE;
209 }
cairo_dock_manage_mouse_position(CairoDock * pDock)210 static void cairo_dock_manage_mouse_position (CairoDock *pDock)
211 {
212 switch (pDock->iMousePositionType)
213 {
214 case CAIRO_DOCK_MOUSE_INSIDE :
215 //g_print ("INSIDE (%d;%d;%d;%d;%d)\n", cairo_dock_entrance_is_allowed (pDock), pDock->iMagnitudeIndex, pDock->bIsGrowingUp, pDock->bIsShrinkingDown, pDock->iInputState);
216 if (cairo_dock_entrance_is_allowed (pDock)
217 && ((pDock->iMagnitudeIndex < CAIRO_DOCK_NB_MAX_ITERATIONS
218 && ! pDock->bIsGrowingUp)
219 || pDock->bIsShrinkingDown)
220 && pDock->iInputState != CAIRO_DOCK_INPUT_HIDDEN
221 && (pDock->iInputState != CAIRO_DOCK_INPUT_AT_REST
222 || pDock->bIsDragging))
223 /* We are inside and icons' size is not the maximum even if
224 * the dock is not growing but we respect the 'cache' and
225 * 'idle' states
226 */
227 {
228 if (pDock->iRefCount != 0 && !pDock->container.bInside)
229 {
230
231 break;
232 }
233 //pDock->container.bInside = TRUE;
234 /* we do it not with 'auto-hide' mode because a entry signal is
235 * already sent due to the movements and resize of the window
236 * and we re-add it one here and it's a problem
237 * '! pDock->container.bInside' has been added to fix the bug
238 * when switching between desktops
239 if ((pDock->bAtBottom && pDock->iRefCount == 0
240 && ! pDock->bAutoHide)
241 || (pDock->container.iWidth != pDock->iMaxDockWidth
242 || pDock->container.iHeight != pDock->iMaxDockHeight)
243 || ! pDock->container.bInside)
244 */
245 if ((pDock->iMagnitudeIndex == 0 && pDock->iRefCount == 0
246 && ! pDock->bAutoHide && ! pDock->bIsGrowingUp)
247 || !pDock->container.bInside)
248 /* we are probably a little bit paranoia here, especially
249 * with the first case ... anyway, if we missed the
250 * 'enter' event for some reason, force it here.
251 */
252 {
253 //g_print (" we emulate a re-entry (pDock->iMagnitudeIndex:%d)\n", pDock->iMagnitudeIndex);
254 cairo_dock_emit_enter_signal (CAIRO_CONTAINER (pDock));
255 }
256 else // we settle for growing icons
257 {
258 //g_print (" we settle for growing icons\n");
259 cairo_dock_start_growing (pDock);
260 if (pDock->bAutoHide && pDock->iRefCount == 0)
261 cairo_dock_start_showing (pDock);
262 }
263 }
264 break ;
265
266 case CAIRO_DOCK_MOUSE_ON_THE_EDGE :
267 if (pDock->iMagnitudeIndex > 0 && ! pDock->bIsGrowingUp)
268 cairo_dock_start_shrinking (pDock);
269 break ;
270
271 case CAIRO_DOCK_MOUSE_OUTSIDE :
272 //g_print ("en dehors du dock (bIsShrinkingDown:%d;bIsGrowingUp:%d;iMagnitudeIndex:%d)\n", pDock->bIsShrinkingDown, pDock->bIsGrowingUp, pDock->iMagnitudeIndex);
273 if (! pDock->bIsGrowingUp && ! pDock->bIsShrinkingDown
274 && pDock->iSidLeaveDemand == 0 && pDock->iMagnitudeIndex > 0
275 && ! pDock->bIconIsFlyingAway)
276 {
277 if (pDock->iRefCount > 0)
278 {
279 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
280 if (pPointingIcon && pPointingIcon->bPointed) // sous-dock pointe, on le laisse en position haute.
281 return;
282 }
283 //g_print ("on force a quitter (iRefCount:%d; bIsGrowingUp:%d; iMagnitudeIndex:%d)\n", pDock->iRefCount, pDock->bIsGrowingUp, pDock->iMagnitudeIndex);
284 pDock->iSidLeaveDemand = g_timeout_add (MAX (myDocksParam.iLeaveSubDockDelay, 300), (GSourceFunc) _emit_leave_signal_delayed, (gpointer) pDock);
285 }
286 break ;
287 }
288 }
cairo_dock_calculate_dock_icons(CairoDock * pDock)289 Icon *cairo_dock_calculate_dock_icons (CairoDock *pDock)
290 {
291 Icon *pPointedIcon = pDock->pRenderer->calculate_icons (pDock);
292 cairo_dock_manage_mouse_position (pDock);
293 return pPointedIcon;
294 /**if (pDock->iMousePositionType == CAIRO_DOCK_MOUSE_INSIDE)
295 {
296 return pPointedIcon;
297 }
298 else
299 {
300 if (pPointedIcon)
301 pPointedIcon->bPointed = FALSE;
302 return NULL;
303 }*/
304 }
305
306
307
308 ////////////////////////////////
309 /// WINDOW SIZE AND POSITION ///
310 ////////////////////////////////
311
312 #define CANT_RESERVE_SPACE_WARNING "It's only possible to reserve space from the edge of the screen and not on the middle of two screens."
313
314 #define _has_multiple_screens_and_on_one_screen(iNumScreen) (g_desktopGeometry.iNbScreens > 1 && iNumScreen > -1)
315
cairo_dock_reserve_space_for_dock(CairoDock * pDock,gboolean bReserve)316 void cairo_dock_reserve_space_for_dock (CairoDock *pDock, gboolean bReserve)
317 {
318 int left=0, right=0, top=0, bottom=0;
319 int left_start_y=0, left_end_y=0, right_start_y=0, right_end_y=0, top_start_x=0, top_end_x=0, bottom_start_x=0, bottom_end_x=0;
320
321 if (bReserve)
322 {
323 int w = pDock->iMinDockWidth;
324 int h = pDock->iMinDockHeight;
325 int x, y; // position that should have dock's window if it has a minimum size.
326 cairo_dock_get_window_position_at_balance (pDock, w, h, &x, &y);
327
328 if (pDock->container.bDirectionUp)
329 {
330 if (pDock->container.bIsHorizontal)
331 {
332 if (_has_multiple_screens_and_on_one_screen (pDock->iNumScreen)
333 && cairo_dock_get_screen_position_y (pDock->iNumScreen) // y offset
334 + cairo_dock_get_screen_height (pDock->iNumScreen) // height of the current screen
335 < gldi_desktop_get_height ()) // total height
336 cd_warning (CANT_RESERVE_SPACE_WARNING);
337 else
338 {
339 bottom = h + pDock->iGapY;
340 bottom_start_x = x;
341 bottom_end_x = x + w;
342 }
343 }
344 else
345 {
346 if (_has_multiple_screens_and_on_one_screen (pDock->iNumScreen)
347 && cairo_dock_get_screen_position_x (pDock->iNumScreen) // x offset
348 + cairo_dock_get_screen_width (pDock->iNumScreen) // width of the current screen
349 < gldi_desktop_get_width ()) // total width
350 cd_warning (CANT_RESERVE_SPACE_WARNING);
351 else
352 {
353 right = h + pDock->iGapY;
354 right_start_y = x;
355 right_end_y = x + w;
356 }
357 }
358 }
359 else
360 {
361 if (pDock->container.bIsHorizontal)
362 {
363 if (_has_multiple_screens_and_on_one_screen (pDock->iNumScreen)
364 && cairo_dock_get_screen_position_y (pDock->iNumScreen) > 0)
365 cd_warning (CANT_RESERVE_SPACE_WARNING);
366 else
367 {
368 top = h + pDock->iGapY;
369 top_start_x = x;
370 top_end_x = x + w;
371 }
372 }
373 else
374 {
375 if (_has_multiple_screens_and_on_one_screen (pDock->iNumScreen)
376 && cairo_dock_get_screen_position_x (pDock->iNumScreen) > 0)
377 cd_warning (CANT_RESERVE_SPACE_WARNING);
378 else
379 {
380 left = h + pDock->iGapY;
381 left_start_y = x;
382 left_end_y = x + w;
383 }
384 }
385 }
386 }
387 gldi_container_reserve_space (CAIRO_CONTAINER(pDock), left, right, top, bottom, left_start_y, left_end_y, right_start_y, right_end_y, top_start_x, top_end_x, bottom_start_x, bottom_end_x);
388 }
389
cairo_dock_prevent_dock_from_out_of_screen(CairoDock * pDock)390 void cairo_dock_prevent_dock_from_out_of_screen (CairoDock *pDock)
391 {
392 int x, y; // position of the invariant point of the dock.
393 x = pDock->container.iWindowPositionX + pDock->container.iWidth * pDock->fAlign;
394 y = (pDock->container.bDirectionUp ? pDock->container.iWindowPositionY + pDock->container.iHeight : pDock->container.iWindowPositionY);
395 //cd_debug ("%s (%d;%d)", __func__, x, y);
396
397 int W = gldi_dock_get_screen_width (pDock), H = gldi_dock_get_screen_height (pDock);
398 pDock->iGapX = x - W * pDock->fAlign;
399 pDock->iGapY = (pDock->container.bDirectionUp ? H - y : y);
400 //cd_debug (" -> (%d;%d)", pDock->iGapX, pDock->iGapY);
401
402 if (pDock->iGapX < - W/2)
403 pDock->iGapX = - W/2;
404 if (pDock->iGapX > W/2)
405 pDock->iGapX = W/2;
406 if (pDock->iGapY < 0)
407 pDock->iGapY = 0;
408 if (pDock->iGapY > H)
409 pDock->iGapY = H;
410 }
411
412 #define CD_VISIBILITY_MARGIN 20
cairo_dock_get_window_position_at_balance(CairoDock * pDock,int iNewWidth,int iNewHeight,int * iNewPositionX,int * iNewPositionY)413 void cairo_dock_get_window_position_at_balance (CairoDock *pDock, int iNewWidth, int iNewHeight, int *iNewPositionX, int *iNewPositionY)
414 {
415 int W = gldi_dock_get_screen_width (pDock), H = gldi_dock_get_screen_height (pDock);
416 int iWindowPositionX = (W - iNewWidth) * pDock->fAlign + pDock->iGapX;
417 if (pDock->iRefCount == 0 && pDock->fAlign != .5)
418 iWindowPositionX += (.5 - pDock->fAlign) * (pDock->iMaxDockWidth - iNewWidth);
419 int iWindowPositionY = (pDock->container.bDirectionUp ? H - iNewHeight - pDock->iGapY : pDock->iGapY);
420 //g_print ("pDock->iGapX : %d => iWindowPositionX <- %d\n", pDock->iGapX, iWindowPositionX);
421 //g_print ("iNewHeight : %d -> pDock->container.iWindowPositionY <- %d\n", iNewHeight, iWindowPositionY);
422
423 if (pDock->iRefCount == 0)
424 {
425 if (iWindowPositionX + iNewWidth < CD_VISIBILITY_MARGIN)
426 iWindowPositionX = CD_VISIBILITY_MARGIN - iNewWidth;
427 else if (iWindowPositionX > W - CD_VISIBILITY_MARGIN)
428 iWindowPositionX = W - CD_VISIBILITY_MARGIN;
429 }
430 else
431 {
432 if (iWindowPositionX < - pDock->iLeftMargin)
433 iWindowPositionX = - pDock->iLeftMargin;
434 else if (iWindowPositionX > W - iNewWidth + pDock->iMinRightMargin)
435 iWindowPositionX = W - iNewWidth + pDock->iMinRightMargin;
436 }
437 if (iWindowPositionY < - pDock->iMaxIconHeight)
438 iWindowPositionY = - pDock->iMaxIconHeight;
439 else if (iWindowPositionY > H - iNewHeight + pDock->iMaxIconHeight)
440 iWindowPositionY = H - iNewHeight + pDock->iMaxIconHeight;
441
442 *iNewPositionX = iWindowPositionX + gldi_dock_get_screen_offset_x (pDock);
443 *iNewPositionY = iWindowPositionY + gldi_dock_get_screen_offset_y (pDock);
444 //g_print ("POSITION : %d+%d ; %d+%d\n", iWindowPositionX, pDock->iScreenOffsetX, iWindowPositionY, pDock->iScreenOffsetY);
445 }
446
_move_resize_dock(CairoDock * pDock)447 static gboolean _move_resize_dock (CairoDock *pDock)
448 {
449 int iNewWidth = pDock->iMaxDockWidth;
450 int iNewHeight = pDock->iMaxDockHeight;
451 int iNewPositionX, iNewPositionY;
452 cairo_dock_get_window_position_at_balance (pDock, iNewWidth, iNewHeight, &iNewPositionX, &iNewPositionY);
453 /* We can't intercept the case where the new dimensions == current ones
454 * because we can have 2 resizes at the "same" time and they will cancel
455 * themselves (remove + insert of one icon). We need 2 configure otherwise
456 * the size will be blocked to the value of the first 'configure'
457 */
458 //g_print (" -> %dx%d, %d;%d\n", iNewWidth, iNewHeight, iNewPositionX, iNewPositionY);
459
460 if (pDock->container.bIsHorizontal)
461 {
462 gdk_window_move_resize (gldi_container_get_gdk_window (CAIRO_CONTAINER (pDock)),
463 iNewPositionX,
464 iNewPositionY,
465 iNewWidth,
466 iNewHeight);
467 /* When we have two gdk_window_move_resize in a row, Compiz will
468 * disturbed and it will block the draw of the dock. It seems Compiz
469 * sends too much 'configure' compare to Metacity.
470 */
471 }
472 else
473 {
474 gdk_window_move_resize (gldi_container_get_gdk_window (CAIRO_CONTAINER (pDock)),
475 iNewPositionY,
476 iNewPositionX,
477 iNewHeight,
478 iNewWidth);
479 }
480 pDock->iSidMoveResize = 0;
481 return FALSE;
482 }
483
cairo_dock_move_resize_dock(CairoDock * pDock)484 void cairo_dock_move_resize_dock (CairoDock *pDock)
485 {
486 //g_print ("*********%s (current : %dx%d, %d;%d)\n", __func__, pDock->container.iWidth, pDock->container.iHeight, pDock->container.iWindowPositionX, pDock->container.iWindowPositionY);
487 if (pDock->iSidMoveResize == 0)
488 {
489 pDock->iSidMoveResize = g_idle_add ((GSourceFunc)_move_resize_dock, pDock);
490 }
491 return ;
492 }
493
494
495 ///////////////////
496 /// INPUT SHAPE ///
497 ///////////////////
_cairo_dock_create_input_shape(CairoDock * pDock,int w,int h)498 static cairo_region_t *_cairo_dock_create_input_shape (CairoDock *pDock, int w, int h)
499 {
500 int W = pDock->iMaxDockWidth;
501 int H = pDock->iMaxDockHeight;
502 if (W == 0 || H == 0) // very unlikely to happen, but anyway avoid this case.
503 {
504 return NULL;
505 }
506
507 double offset = (W - pDock->iActiveWidth) * pDock->fAlign + (pDock->iActiveWidth - w) / 2;
508
509 cairo_region_t *pShapeBitmap;
510 if (pDock->container.bIsHorizontal)
511 {
512 pShapeBitmap = gldi_container_create_input_shape (CAIRO_CONTAINER (pDock),
513 ///(W - w) * pDock->fAlign,
514 offset,
515 pDock->container.bDirectionUp ? H - h : 0,
516 w,
517 h);
518 }
519 else
520 {
521 pShapeBitmap = gldi_container_create_input_shape (CAIRO_CONTAINER (pDock),
522 pDock->container.bDirectionUp ? H - h : 0,
523 ///(W - w) * pDock->fAlign,
524 offset,
525 h,
526 w);
527 }
528 return pShapeBitmap;
529 }
530
cairo_dock_update_input_shape(CairoDock * pDock)531 void cairo_dock_update_input_shape (CairoDock *pDock)
532 {
533 //\_______________ destroy the current input zones.
534 if (pDock->pShapeBitmap != NULL)
535 {
536 cairo_region_destroy (pDock->pShapeBitmap);
537 pDock->pShapeBitmap = NULL;
538 }
539 if (pDock->pHiddenShapeBitmap != NULL)
540 {
541 cairo_region_destroy (pDock->pHiddenShapeBitmap);
542 pDock->pHiddenShapeBitmap = NULL;
543 }
544 if (pDock->pActiveShapeBitmap != NULL)
545 {
546 cairo_region_destroy (pDock->pActiveShapeBitmap);
547 pDock->pActiveShapeBitmap = NULL;
548 }
549
550 //\_______________ define the input zones' geometry
551 int W = pDock->iMaxDockWidth;
552 int H = pDock->iMaxDockHeight;
553 int w = pDock->iMinDockWidth;
554 int h = pDock->iMinDockHeight;
555 //g_print ("%s (%dx%d; %dx%d)\n", __func__, w, h, W, H);
556 int w_ = 0; // Note: in older versions of X, a fully empty input shape was not working and we had to set 1 pixel ON.
557 int h_ = 0;
558
559 //\_______________ check that the dock can have input zones.
560 if (w == 0 || h == 0 || pDock->iRefCount > 0 || W == 0 || H == 0)
561 {
562 if (pDock->iActiveWidth != pDock->iMaxDockWidth || pDock->iActiveHeight != pDock->iMaxDockHeight)
563 // else all the dock is active when the mouse is inside, so we can just set a NULL shape.
564 pDock->pActiveShapeBitmap = _cairo_dock_create_input_shape (pDock, pDock->iActiveWidth, pDock->iActiveHeight);
565 if (pDock->iInputState != CAIRO_DOCK_INPUT_ACTIVE)
566 {
567 //g_print ("+++ input shape active on update input shape\n");
568 cairo_dock_set_input_shape_active (pDock);
569 pDock->iInputState = CAIRO_DOCK_INPUT_ACTIVE;
570 }
571 return ;
572 }
573
574 //\_______________ create the input zones based on the previous geometries.
575 pDock->pShapeBitmap = _cairo_dock_create_input_shape (pDock, w, h);
576
577 pDock->pHiddenShapeBitmap = _cairo_dock_create_input_shape (pDock, w_, h_);
578
579 if (pDock->iActiveWidth != pDock->iMaxDockWidth || pDock->iActiveHeight != pDock->iMaxDockHeight)
580 // else all the dock is active when the mouse is inside, so we can just set a NULL shape.
581 pDock->pActiveShapeBitmap = _cairo_dock_create_input_shape (pDock, pDock->iActiveWidth, pDock->iActiveHeight);
582
583 //\_______________ if the renderer can define the input shape, let it finish the job.
584 if (pDock->pRenderer->update_input_shape != NULL)
585 pDock->pRenderer->update_input_shape (pDock);
586 }
587
588
589
590 ///////////////////
591 /// LINEAR DOCK ///
592 ///////////////////
593
cairo_dock_calculate_icons_positions_at_rest_linear(GList * pIconList,double fFlatDockWidth)594 void cairo_dock_calculate_icons_positions_at_rest_linear (GList *pIconList, double fFlatDockWidth)
595 {
596 //g_print ("%s (%d, +%d)\n", __func__, fFlatDockWidth);
597 double x_cumulated = 0;
598 GList* ic;
599 Icon *icon;
600 for (ic = pIconList; ic != NULL; ic = ic->next)
601 {
602 icon = ic->data;
603
604 if (x_cumulated + icon->fWidth / 2 < 0)
605 icon->fXAtRest = x_cumulated + fFlatDockWidth;
606 else if (x_cumulated + icon->fWidth / 2 > fFlatDockWidth)
607 icon->fXAtRest = x_cumulated - fFlatDockWidth;
608 else
609 icon->fXAtRest = x_cumulated;
610 //g_print ("%s : fXAtRest = %.2f\n", icon->cName, icon->fXAtRest);
611
612 x_cumulated += icon->fWidth + myIconsParam.iIconGap;
613 }
614 }
615
cairo_dock_calculate_max_dock_width(CairoDock * pDock,double fFlatDockWidth,double fWidthConstraintFactor,double fExtraWidth)616 double cairo_dock_calculate_max_dock_width (CairoDock *pDock, double fFlatDockWidth, double fWidthConstraintFactor, double fExtraWidth)
617 {
618 double fMaxDockWidth = 0.;
619 //g_print ("%s (%d)\n", __func__, (int)fFlatDockWidth);
620 GList *pIconList = pDock->icons;
621 if (pIconList == NULL)
622 return 2 * myDocksParam.iDockRadius + myDocksParam.iDockLineWidth + 2 * myDocksParam.iFrameMargin;
623
624 // We reset extreme positions of the icons.
625 GList* ic;
626 Icon *icon;
627 for (ic = pIconList; ic != NULL; ic = ic->next)
628 {
629 icon = ic->data;
630 icon->fXMax = -1e4;
631 icon->fXMin = 1e4;
632 }
633
634 /* We simulate the move of the cursor in all the width of the dock and we
635 * get the maximum width and the balance position for each icon.
636 */
637 GList *ic2;
638 for (ic = pIconList; ic != NULL; ic = ic->next)
639 {
640 icon = ic->data;
641
642 cairo_dock_calculate_wave_with_position_linear (pIconList, icon->fXAtRest, pDock->fMagnitudeMax, fFlatDockWidth, 0, 0, 0.5, 0, pDock->container.bDirectionUp);
643
644 for (ic2 = pIconList; ic2 != NULL; ic2 = ic2->next)
645 {
646 icon = ic2->data;
647
648 if (icon->fX + icon->fWidth * icon->fScale > icon->fXMax)
649 icon->fXMax = icon->fX + icon->fWidth * icon->fScale;
650 if (icon->fX < icon->fXMin)
651 icon->fXMin = icon->fX;
652 }
653 }
654 cairo_dock_calculate_wave_with_position_linear (pIconList, fFlatDockWidth - 1, pDock->fMagnitudeMax, fFlatDockWidth, 0, 0, pDock->fAlign, 0, pDock->container.bDirectionUp); // last calculation at the extreme right of the dock.
655 for (ic = pIconList; ic != NULL; ic = ic->next)
656 {
657 icon = ic->data;
658
659 if (icon->fX + icon->fWidth * icon->fScale > icon->fXMax)
660 icon->fXMax = icon->fX + icon->fWidth * icon->fScale;
661 if (icon->fX < icon->fXMin)
662 icon->fXMin = icon->fX;
663 }
664
665 fMaxDockWidth = (icon->fXMax - ((Icon *) pIconList->data)->fXMin) * fWidthConstraintFactor + fExtraWidth;
666 fMaxDockWidth = ceil (fMaxDockWidth) + 1;
667
668 for (ic = pIconList; ic != NULL; ic = ic->next)
669 {
670 icon = ic->data;
671 icon->fXMin += fMaxDockWidth / 2;
672 icon->fXMax += fMaxDockWidth / 2;
673 //g_print ("%s : [%d;%d]\n", icon->cName, (int) icon->fXMin, (int) icon->fXMax);
674 icon->fX = icon->fXAtRest;
675 icon->fScale = 1;
676 }
677
678 return fMaxDockWidth;
679 }
680
cairo_dock_calculate_wave_with_position_linear(GList * pIconList,int x_abs,gdouble fMagnitude,double fFlatDockWidth,int iWidth,int iHeight,double fAlign,double fFoldingFactor,gboolean bDirectionUp)681 Icon * cairo_dock_calculate_wave_with_position_linear (GList *pIconList, int x_abs, gdouble fMagnitude, double fFlatDockWidth, int iWidth, int iHeight, double fAlign, double fFoldingFactor, gboolean bDirectionUp)
682 {
683 //g_print (">>>>>%s (%d/%.2f, %dx%d, %.2f, %.2f)\n", __func__, x_abs, fFlatDockWidth, iWidth, iHeight, fAlign, fFoldingFactor);
684 if (pIconList == NULL)
685 return NULL;
686 if (x_abs < 0 && iWidth > 0)
687 // to avoid too quick resize when leaving from the edges.
688 ///x_abs = -1;
689 x_abs = 0;
690 else if (x_abs > fFlatDockWidth && iWidth > 0)
691 ///x_abs = fFlatDockWidth+1;
692 x_abs = (int) fFlatDockWidth;
693
694
695 float x_cumulated = 0, fXMiddle, fDeltaExtremum;
696 GList* ic, *pointed_ic;
697 Icon *icon, *prev_icon;
698 double fScale = 0.;
699 double offset = 0.;
700 pointed_ic = (x_abs < 0 ? pIconList : NULL);
701 for (ic = pIconList; ic != NULL; ic = ic->next)
702 {
703 icon = ic->data;
704 x_cumulated = icon->fXAtRest;
705 fXMiddle = icon->fXAtRest + icon->fWidth / 2;
706
707 //\_______________ We compute its phase (pi/2 next to the cursor).
708 icon->fPhase = (fXMiddle - x_abs) / myIconsParam.iSinusoidWidth * G_PI + G_PI / 2;
709 if (icon->fPhase < 0)
710 {
711 icon->fPhase = 0;
712 }
713 else if (icon->fPhase > G_PI)
714 {
715 icon->fPhase = G_PI;
716 }
717
718 //\_______________ We deduct the sinusoidal amplitude next to the icon (its scale)
719 icon->fScale = 1 + fMagnitude * myIconsParam.fAmplitude * sin (icon->fPhase);
720 if (iWidth > 0 && icon->fInsertRemoveFactor != 0)
721 {
722 fScale = icon->fScale;
723 ///offset += (icon->fWidth * icon->fScale) * (pointed_ic == NULL ? 1 : -1);
724 if (icon->fInsertRemoveFactor > 0)
725 icon->fScale *= icon->fInsertRemoveFactor;
726 else
727 icon->fScale *= (1 + icon->fInsertRemoveFactor);
728 ///offset -= (icon->fWidth * icon->fScale) * (pointed_ic == NULL ? 1 : -1);
729 }
730
731 icon->fY = (bDirectionUp ? iHeight - myDocksParam.iDockLineWidth - myDocksParam.iFrameMargin - icon->fScale * icon->fHeight : myDocksParam.iDockLineWidth + myDocksParam.iFrameMargin);
732 //g_print ("%s fY : %d; %.2f\n", icon->cName, iHeight, icon->fHeight);
733
734 /* If we already have defined a pointed icon, we can move the current
735 * icon compared to the previous one
736 */
737 if (pointed_ic != NULL)
738 {
739 if (ic == pIconList) // can happen if we are outside from the left of the dock.
740 {
741 icon->fX = x_cumulated - 1. * (fFlatDockWidth - iWidth) / 2;
742 //g_print (" outside from the left : icon->fX = %.2f (%.2f)\n", icon->fX, x_cumulated);
743 }
744 else
745 {
746 prev_icon = (ic->prev != NULL ? ic->prev->data : cairo_dock_get_last_icon (pIconList));
747 icon->fX = prev_icon->fX + (prev_icon->fWidth + myIconsParam.iIconGap) * prev_icon->fScale;
748
749 if (icon->fX + icon->fWidth * icon->fScale > icon->fXMax - myIconsParam.fAmplitude * fMagnitude * (icon->fWidth + 1.5*myIconsParam.iIconGap) / 8 && iWidth != 0)
750 {
751 //g_print (" we constraint %s (fXMax=%.2f , fX=%.2f\n", prev_icon->cName, prev_icon->fXMax, prev_icon->fX);
752 fDeltaExtremum = icon->fX + icon->fWidth * icon->fScale - (icon->fXMax - myIconsParam.fAmplitude * fMagnitude * (icon->fWidth + 1.5*myIconsParam.iIconGap) / 16);
753 if (myIconsParam.fAmplitude != 0)
754 icon->fX -= fDeltaExtremum * (1 - (icon->fScale - 1) / myIconsParam.fAmplitude) * fMagnitude;
755 }
756 }
757 icon->fX = fAlign * iWidth + (icon->fX - fAlign * iWidth) * (1. - fFoldingFactor);
758 //g_print (" on the right : icon->fX = %.2f (%.2f)\n", icon->fX, x_cumulated);
759 }
760
761 //\_______________ We check if we have a pointer on this icon.
762 if (pointed_ic == NULL
763 && x_cumulated + icon->fWidth + .5*myIconsParam.iIconGap >= x_abs
764 && x_cumulated - .5*myIconsParam.iIconGap <= x_abs) // we found the pointed icon.
765 {
766 pointed_ic = ic;
767 ///icon->bPointed = TRUE;
768 icon->bPointed = (x_abs != (int) fFlatDockWidth && x_abs != 0);
769 icon->fX = x_cumulated - (fFlatDockWidth - iWidth) / 2 + (1 - icon->fScale) * (x_abs - x_cumulated + .5*myIconsParam.iIconGap);
770 icon->fX = fAlign * iWidth + (icon->fX - fAlign * iWidth) * (1. - fFoldingFactor);
771 //g_print (" pointed icon: fX = %.2f (%.2f, %d)\n", icon->fX, x_cumulated, icon->bPointed);
772 }
773 else
774 icon->bPointed = FALSE;
775
776 if (iWidth > 0 && icon->fInsertRemoveFactor != 0)
777 {
778 if (pointed_ic != ic) // bPointed can be false for the last icon on the right.
779 offset += (icon->fWidth * (fScale - icon->fScale)) * (pointed_ic == NULL ? 1 : -1);
780 else
781 offset += (2*(fXMiddle - x_abs) * (fScale - icon->fScale)) * (pointed_ic == NULL ? 1 : -1);
782 }
783 }
784
785 //\_______________ We place icons before pointed icon beside this one
786 if (pointed_ic == NULL) // We are at the right of icons.
787 {
788 pointed_ic = g_list_last (pIconList);
789 icon = pointed_ic->data;
790 icon->fX = x_cumulated - (fFlatDockWidth - iWidth) / 2 + (1 - icon->fScale) * (icon->fWidth + .5*myIconsParam.iIconGap);
791 icon->fX = fAlign * iWidth + (icon->fX - fAlign * iWidth) * (1 - fFoldingFactor);
792 //g_print (" outside on the right: icon->fX = %.2f (%.2f)\n", icon->fX, x_cumulated);
793 }
794
795 ic = pointed_ic;
796 while (ic != pIconList)
797 {
798 icon = ic->data;
799
800 ic = ic->prev; // since ic != pIconList, ic->prev is not NULL
801 prev_icon = ic->data;
802
803 prev_icon->fX = icon->fX - (prev_icon->fWidth + myIconsParam.iIconGap) * prev_icon->fScale;
804 //g_print ("fX <- %.2f; fXMin : %.2f\n", prev_icon->fX, prev_icon->fXMin);
805 if (prev_icon->fX < prev_icon->fXMin + myIconsParam.fAmplitude * fMagnitude * (prev_icon->fWidth + 1.5*myIconsParam.iIconGap) / 8
806 && iWidth != 0 && x_abs < iWidth && fMagnitude > 0) /// && prev_icon->fPhase == 0
807 // We re-add 'fMagnitude > 0' otherwise we have a small jump due to constraints on the left of the pointed icon.
808 {
809 //g_print (" we constraint %s (fXMin=%.2f , fX=%.2f\n", prev_icon->cName, prev_icon->fXMin, prev_icon->fX);
810 fDeltaExtremum = prev_icon->fX - (prev_icon->fXMin + myIconsParam.fAmplitude * fMagnitude * (prev_icon->fWidth + 1.5*myIconsParam.iIconGap) / 16);
811 if (myIconsParam.fAmplitude != 0)
812 prev_icon->fX -= fDeltaExtremum * (1 - (prev_icon->fScale - 1) / myIconsParam.fAmplitude) * fMagnitude;
813 }
814 prev_icon->fX = fAlign * iWidth + (prev_icon->fX - fAlign * iWidth) * (1. - fFoldingFactor);
815 //g_print (" prev_icon->fX : %.2f\n", prev_icon->fX);
816 }
817
818 if (offset != 0)
819 {
820 offset /= 2;
821 //g_print ("offset : %.2f (pointed:%s)\n", offset, pointed_ic?((Icon*)pointed_ic->data)->cName:"none");
822 for (ic = pIconList; ic != NULL; ic = ic->next)
823 {
824 icon = ic->data;
825 //if (ic == pIconList)
826 // cd_debug ("fX : %.2f - %.2f", icon->fX, offset);
827 icon->fX -= offset;
828 }
829 }
830
831 icon = pointed_ic->data;
832 return (icon->bPointed ? icon : NULL);
833 }
834
cairo_dock_apply_wave_effect_linear(CairoDock * pDock)835 Icon *cairo_dock_apply_wave_effect_linear (CairoDock *pDock)
836 {
837 //\_______________ We compute the cursor's position in the container of the flat dock
838 //int dx = pDock->container.iMouseX - (pDock->iOffsetForExtend * (pDock->fAlign - .5) * 2) - pDock->container.iWidth / 2; // gap compare to the middle of the flat dock.
839 //int x_abs = dx + pDock->fFlatDockWidth / 2; // gap compare to the left of the minimal flat dock.
840 //g_print ("%s (flat:%d, w:%d, x:%d)\n", __func__, (int)pDock->fFlatDockWidth, pDock->container.iWidth, pDock->container.iMouseX);
841 double offset = (pDock->container.iWidth - pDock->iActiveWidth) * pDock->fAlign + (pDock->iActiveWidth - pDock->fFlatDockWidth) / 2;
842 int x_abs = pDock->container.iMouseX - offset;
843
844 //\_______________ We compute all parameters for the icons.
845 double fMagnitude = cairo_dock_calculate_magnitude (pDock->iMagnitudeIndex); // * pDock->fMagnitudeMax
846 Icon *pPointedIcon = cairo_dock_calculate_wave_with_position_linear (pDock->icons, x_abs, fMagnitude, pDock->fFlatDockWidth, pDock->container.iWidth, pDock->container.iHeight, pDock->fAlign, pDock->fFoldingFactor, pDock->container.bDirectionUp); // iMaxDockWidth
847 return pPointedIcon;
848 }
849
cairo_dock_get_current_dock_width_linear(CairoDock * pDock)850 double cairo_dock_get_current_dock_width_linear (CairoDock *pDock)
851 {
852 if (pDock->icons == NULL)
853 //return 2 * myDocksParam.iDockRadius + myDocksParam.iDockLineWidth + 2 * myDocksParam.iFrameMargin;
854 return 1 + 2 * myDocksParam.iFrameMargin;
855
856 Icon *pLastIcon = cairo_dock_get_last_icon (pDock->icons);
857 Icon *pFirstIcon = cairo_dock_get_first_icon (pDock->icons);
858 double fWidth = pLastIcon->fX - pFirstIcon->fX + pLastIcon->fWidth * pLastIcon->fScale + 2 * myDocksParam.iFrameMargin; // + 2 * myDocksParam.iDockRadius + myDocksParam.iDockLineWidth + 2 * myDocksParam.iFrameMargin
859
860 return fWidth;
861 }
862
cairo_dock_check_if_mouse_inside_linear(CairoDock * pDock)863 void cairo_dock_check_if_mouse_inside_linear (CairoDock *pDock)
864 {
865 CairoDockMousePositionType iMousePositionType;
866 int iWidth = pDock->container.iWidth;
867 ///int iHeight = (pDock->fMagnitudeMax != 0 ? pDock->container.iHeight : pDock->iMinDockHeight);
868 int iHeight = pDock->iActiveHeight;
869 ///int iExtraHeight = (pDock->bAtBottom ? 0 : myIconsParam.iLabelSize);
870 // int iExtraHeight = 0; /// we should check if we have a sub-dock or a dialogue on top of it :-/
871 int iMouseX = pDock->container.iMouseX;
872 int iMouseY = (pDock->container.bDirectionUp ? pDock->container.iHeight - pDock->container.iMouseY : pDock->container.iMouseY);
873 //g_print ("%s (%dx%d, %dx%d, %f)\n", __func__, iMouseX, iMouseY, iWidth, iHeight, pDock->fFoldingFactor);
874
875 //\_______________ We check if the cursor is in the dock and we change icons size according to that.
876 double offset = (iWidth - pDock->iActiveWidth) * pDock->fAlign + (pDock->iActiveWidth - pDock->fFlatDockWidth) / 2;
877 int x_abs = pDock->container.iMouseX - offset;
878 ///int x_abs = pDock->container.iMouseX + (pDock->fFlatDockWidth - iWidth) * pDock->fAlign; // abscisse par rapport a la gauche du dock minimal plat.
879 gboolean bMouseInsideDock = (x_abs >= 0 && x_abs <= pDock->fFlatDockWidth && iMouseX > 0 && iMouseX < iWidth);
880 //g_print ("bMouseInsideDock : %d (%d;%d/%.2f)\n", bMouseInsideDock, pDock->container.bInside, x_abs, pDock->fFlatDockWidth);
881
882 if (iMouseY >= 0 && iMouseY < iHeight) { // inside in the Y axis
883 if (! bMouseInsideDock) // outside of the dock but on the edge.
884 iMousePositionType = CAIRO_DOCK_MOUSE_ON_THE_EDGE;
885 else
886 iMousePositionType = CAIRO_DOCK_MOUSE_INSIDE;
887 }
888 else
889 iMousePositionType = CAIRO_DOCK_MOUSE_OUTSIDE;
890
891 pDock->iMousePositionType = iMousePositionType;
892 }
893
894
895 #define make_icon_avoid_mouse(icon, sens) do { \
896 cairo_dock_mark_icon_as_avoiding_mouse (icon);\
897 icon->fAlpha = 0.75;\
898 if (myIconsParam.fAmplitude != 0)\
899 icon->fDrawX += icon->fWidth * icon->fScale / 4 * sens; } while (0)
_cairo_dock_check_can_drop_linear(CairoDock * pDock,CairoDockIconGroup iGroup,double fMargin)900 static inline gboolean _cairo_dock_check_can_drop_linear (CairoDock *pDock, CairoDockIconGroup iGroup, double fMargin)
901 {
902 gboolean bCanDrop = FALSE;
903 Icon *icon;
904 GList *ic;
905 for (ic = pDock->icons; ic != NULL; ic = ic->next)
906 {
907 icon = ic->data;
908 if (icon->bPointed)
909 {
910 cd_debug ("icon->fWidth: %d, %.2f", (int)icon->fWidth, icon->fScale);
911 cd_debug ("x: %d / %d", pDock->container.iMouseX, (int)icon->fDrawX);
912 if (pDock->container.iMouseX < icon->fDrawX + icon->fWidth * icon->fScale * fMargin) // we are on the left. // fDrawXAtRest
913 {
914 Icon *prev_icon = (ic->prev ? ic->prev->data : NULL);
915 if (icon->iGroup == iGroup || (prev_icon && prev_icon->iGroup == iGroup))
916 {
917 make_icon_avoid_mouse (icon, 1);
918 if (prev_icon)
919 make_icon_avoid_mouse (prev_icon, -1);
920 //g_print ("%s> <%s\n", prev_icon->cName, icon->cName);
921 bCanDrop = TRUE;
922 }
923 }
924 else if (pDock->container.iMouseX > icon->fDrawX + icon->fWidth * icon->fScale * (1 - fMargin)) // on est a droite. // fDrawXAtRest
925 {
926 Icon *next_icon = (ic->next ? ic->next->data : NULL);
927 if (icon->iGroup == iGroup || (next_icon && next_icon->iGroup == iGroup))
928 {
929 make_icon_avoid_mouse (icon, -1);
930 if (next_icon)
931 make_icon_avoid_mouse (next_icon, 1);
932 //g_print ("%s> <%s\n", icon->cName, next_icon->cName);
933 bCanDrop = TRUE;
934 }
935 ic = ic->next; // we skip it.
936 if (ic == NULL)
937 break;
938 } // else: we are on top of it.
939 }
940 else
941 cairo_dock_stop_marking_icon_as_avoiding_mouse (icon);
942 }
943
944 return bCanDrop;
945 }
946
947
cairo_dock_check_can_drop_linear(CairoDock * pDock)948 void cairo_dock_check_can_drop_linear (CairoDock *pDock)
949 {
950 if (! pDock->bIsDragging) // not dragging, so no drop possible.
951 {
952 pDock->bCanDrop = FALSE;
953 }
954 else if (pDock->icons == NULL) // dragging but no icons, so drop always possible.
955 {
956 pDock->bCanDrop = TRUE;
957 }
958 else // dragging and some icons.
959 {
960 pDock->bCanDrop = _cairo_dock_check_can_drop_linear (pDock, pDock->iAvoidingMouseIconType, pDock->fAvoidingMouseMargin);
961 }
962 }
963
cairo_dock_stop_marking_icons(CairoDock * pDock)964 void cairo_dock_stop_marking_icons (CairoDock *pDock)
965 {
966 if (pDock->icons == NULL)
967 return;
968 //g_print ("%s (%d)\n", __func__, iType);
969
970 Icon *icon;
971 GList *ic;
972 for (ic = pDock->icons; ic != NULL; ic = ic->next)
973 {
974 icon = ic->data;
975 cairo_dock_stop_marking_icon_as_avoiding_mouse (icon);
976 }
977 }
978
979
cairo_dock_set_subdock_position_linear(Icon * pPointedIcon,CairoDock * pDock)980 void cairo_dock_set_subdock_position_linear (Icon *pPointedIcon, CairoDock *pDock)
981 {
982 CairoDock *pSubDock = pPointedIcon->pSubDock;
983 ///int iX = pPointedIcon->fXAtRest - (pDock->fFlatDockWidth - pDock->iMaxDockWidth) / 2 + pPointedIcon->fWidth / 2 + (pDock->iOffsetForExtend * (pDock->fAlign - .5) * 2);
984 //int iX = pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2 + (pDock->iOffsetForExtend * (pDock->fAlign - .5) * 2);
985 int iX = pPointedIcon->fDrawX + pPointedIcon->fWidth * pPointedIcon->fScale / 2;
986 if (pSubDock->container.bIsHorizontal == pDock->container.bIsHorizontal)
987 {
988 pSubDock->fAlign = 0.5;
989 pSubDock->iGapX = iX + pDock->container.iWindowPositionX - gldi_dock_get_screen_offset_x (pDock) - gldi_dock_get_screen_width (pDock) / 2; // here, sub-docks have an alignment of 0.5
990 pSubDock->iGapY = pDock->iGapY + pDock->iActiveHeight;
991 }
992 else
993 {
994 pSubDock->fAlign = (pDock->container.bDirectionUp ? 1 : 0);
995 pSubDock->iGapX = (pDock->iGapY + pDock->iActiveHeight) * (pDock->container.bDirectionUp ? -1 : 1);
996 if (pDock->container.bDirectionUp)
997 pSubDock->iGapY = gldi_dock_get_screen_width (pDock) - (iX + pDock->container.iWindowPositionX - gldi_dock_get_screen_offset_x (pDock)) - pSubDock->iMaxDockHeight / 2; // sub-docks have an alignment of 1
998 else
999 pSubDock->iGapY = iX + pDock->container.iWindowPositionX - pSubDock->iMaxDockHeight / 2; // sub-docks have an alignment of 0
1000 }
1001 }
1002
1003
cairo_dock_get_first_drawn_element_linear(GList * icons)1004 GList *cairo_dock_get_first_drawn_element_linear (GList *icons)
1005 {
1006 Icon *icon;
1007 GList *ic;
1008 GList *pFirstDrawnElement = NULL;
1009 for (ic = icons; ic != NULL; ic = ic->next)
1010 {
1011 icon = ic->data;
1012 if (icon->bPointed)
1013 break ;
1014 }
1015
1016 if (ic == NULL || ic->next == NULL) // last icon or no pointed icon.
1017 pFirstDrawnElement = icons;
1018 else
1019 pFirstDrawnElement = ic->next;
1020 return pFirstDrawnElement;
1021 }
1022
1023
cairo_dock_show_subdock(Icon * pPointedIcon,CairoDock * pParentDock)1024 void cairo_dock_show_subdock (Icon *pPointedIcon, CairoDock *pParentDock)
1025 {
1026 cd_debug ("we show the child dock");
1027 CairoDock *pSubDock = pPointedIcon->pSubDock;
1028 g_return_if_fail (pSubDock != NULL);
1029
1030 if (gldi_container_is_visible (CAIRO_CONTAINER (pSubDock))) // already visible.
1031 {
1032 if (pSubDock->bIsShrinkingDown) // It's decreasing, we reverse the process.
1033 {
1034 cairo_dock_start_growing (pSubDock);
1035 }
1036 return ;
1037 }
1038
1039 // place the sub-dock
1040 pSubDock->pRenderer->set_subdock_position (pPointedIcon, pParentDock);
1041
1042 int iNewWidth = pSubDock->iMaxDockWidth;
1043 int iNewHeight = pSubDock->iMaxDockHeight;
1044 int iNewPositionX, iNewPositionY;
1045 cairo_dock_get_window_position_at_balance (pSubDock, iNewWidth, iNewHeight, &iNewPositionX, &iNewPositionY);
1046
1047 gtk_window_present (GTK_WINDOW (pSubDock->container.pWidget));
1048
1049 if (pSubDock->container.bIsHorizontal)
1050 {
1051 gdk_window_move_resize (gldi_container_get_gdk_window (CAIRO_CONTAINER (pSubDock)),
1052 iNewPositionX,
1053 iNewPositionY,
1054 iNewWidth,
1055 iNewHeight);
1056 }
1057 else
1058 {
1059 gdk_window_move_resize (gldi_container_get_gdk_window (CAIRO_CONTAINER (pSubDock)),
1060 iNewPositionY,
1061 iNewPositionX,
1062 iNewHeight,
1063 iNewWidth);
1064 /* in this case, the sub-dock is over the label, so this one is drawn
1065 * with a low transparency, so we trigger the redraw.
1066 */
1067 gtk_widget_queue_draw (pParentDock->container.pWidget);
1068 }
1069
1070 // animate it
1071 if (myDocksParam.bAnimateSubDock && pSubDock->icons != NULL)
1072 {
1073 pSubDock->fFoldingFactor = .99;
1074 cairo_dock_start_growing (pSubDock); // We start growing icons
1075 /* We re-compute icons' size because the first draw was done with
1076 * parameters of an hidden dock ; or the showed animation can take
1077 * more time than the hidden one.
1078 */
1079 pSubDock->pRenderer->calculate_icons (pSubDock);
1080 }
1081 else
1082 {
1083 pSubDock->fFoldingFactor = 0;
1084 ///gtk_widget_queue_draw (pSubDock->container.pWidget);
1085 }
1086 gldi_object_notify (pPointedIcon, NOTIFICATION_UNFOLD_SUBDOCK, pPointedIcon);
1087
1088 gldi_dialogs_replace_all ();
1089 }
1090
1091
_cairo_dock_dock_is_child(CairoDock * pCurrentDock,CairoDock * pSubDock)1092 static gboolean _cairo_dock_dock_is_child (CairoDock *pCurrentDock, CairoDock *pSubDock)
1093 {
1094 GList *pIconsList;
1095 Icon *pIcon;
1096 // check all icons of this dock (recursively)
1097 for (pIconsList = pCurrentDock->icons; pIconsList != NULL; pIconsList = pIconsList->next)
1098 {
1099 pIcon = pIconsList->data;
1100 if (pIcon->pSubDock != NULL
1101 && (pIcon->pSubDock == pSubDock // this subdock is inside the current dock!
1102 || _cairo_dock_dock_is_child (pIcon->pSubDock, pSubDock))) // check recursively
1103 return TRUE;
1104 }
1105 return FALSE;
1106 }
_add_one_dock_to_list(G_GNUC_UNUSED const gchar * cName,CairoDock * pDock,gpointer * data)1107 static void _add_one_dock_to_list (G_GNUC_UNUSED const gchar *cName, CairoDock *pDock, gpointer *data)
1108 {
1109 CairoDock *pParentDock = data[0];
1110 CairoDock *pSubDock = data[1];
1111
1112 // get user docks only
1113 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
1114 if (pPointingIcon && ! GLDI_OBJECT_IS_STACK_ICON (pPointingIcon))
1115 // avoid sub-docks that are not from the theme (applet sub-docks, class sub-docks, etc).
1116 return;
1117
1118 // ignore the parent dock.
1119 if (pDock == pParentDock)
1120 return;
1121
1122 // ignore any child sub-dock (if it's a subdock).
1123 if (pSubDock != NULL
1124 && (pSubDock == pDock || _cairo_dock_dock_is_child (pSubDock, pDock)))
1125 return;
1126
1127 data[2] = g_list_prepend (data[2], pDock);
1128 }
cairo_dock_get_available_docks(CairoDock * pParentDock,CairoDock * pSubDock)1129 GList *cairo_dock_get_available_docks (CairoDock *pParentDock, CairoDock *pSubDock) // avoid 'pParentDock', and 'pSubDock' and any of its children
1130 {
1131 gpointer data[3] = {pParentDock, pSubDock, NULL};
1132 gldi_docks_foreach ((GHFunc)_add_one_dock_to_list, data);
1133 return data[2];
1134 }
1135
1136
_redraw_subdock_content_idle(Icon * pIcon)1137 static gboolean _redraw_subdock_content_idle (Icon *pIcon)
1138 {
1139 CairoDock *pDock = CAIRO_DOCK(cairo_dock_get_icon_container (pIcon));
1140 if (pDock != NULL)
1141 {
1142 if (pIcon->pSubDock != NULL)
1143 {
1144 cairo_dock_draw_subdock_content_on_icon (pIcon, pDock);
1145 }
1146 else
1147 {
1148 /* the icon could lose its sub-dock in the meantime
1149 (e.g. a class having 2 icons and we remove one of these icons)
1150 */
1151 cairo_dock_reload_icon_image (pIcon, CAIRO_CONTAINER (pDock));
1152 }
1153 cairo_dock_redraw_icon (pIcon);
1154 if (pDock->iRefCount != 0 && ! pIcon->bDamaged) // now that the icon image is correct, redraw the pointing icon if needed
1155 cairo_dock_trigger_redraw_subdock_content (pDock);
1156 }
1157 pIcon->iSidRedrawSubdockContent = 0;
1158 return FALSE;
1159 }
cairo_dock_trigger_redraw_subdock_content(CairoDock * pDock)1160 void cairo_dock_trigger_redraw_subdock_content (CairoDock *pDock)
1161 {
1162 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pDock, NULL);
1163 //g_print ("%s (%s, %d)\n", __func__, pPointingIcon?pPointingIcon->cName:NULL, pPointingIcon?pPointingIcon->iSubdockViewType:0);
1164 if (pPointingIcon != NULL && (pPointingIcon->iSubdockViewType != 0 || (pPointingIcon->cClass != NULL && ! myIndicatorsParam.bUseClassIndic && (CAIRO_DOCK_ICON_TYPE_IS_CLASS_CONTAINER (pPointingIcon) || GLDI_OBJECT_IS_LAUNCHER_ICON (pPointingIcon)))))
1165 {
1166 /* if we already have an expected re-draw, we go to the end in order to
1167 * not do it before the redraw of icon linked to this trigger
1168 */
1169 if (pPointingIcon->iSidRedrawSubdockContent != 0)
1170 g_source_remove (pPointingIcon->iSidRedrawSubdockContent);
1171 pPointingIcon->iSidRedrawSubdockContent = g_idle_add ((GSourceFunc) _redraw_subdock_content_idle, pPointingIcon);
1172 }
1173 }
1174
cairo_dock_trigger_redraw_subdock_content_on_icon(Icon * icon)1175 void cairo_dock_trigger_redraw_subdock_content_on_icon (Icon *icon)
1176 {
1177 if (icon->iSidRedrawSubdockContent != 0)
1178 g_source_remove (icon->iSidRedrawSubdockContent);
1179 icon->iSidRedrawSubdockContent = g_idle_add ((GSourceFunc) _redraw_subdock_content_idle, icon);
1180 }
1181
cairo_dock_redraw_subdock_content(CairoDock * pDock)1182 void cairo_dock_redraw_subdock_content (CairoDock *pDock)
1183 {
1184 CairoDock *pParentDock = NULL;
1185 Icon *pPointingIcon = cairo_dock_search_icon_pointing_on_dock (pDock, &pParentDock);
1186 if (pPointingIcon != NULL && pPointingIcon->iSubdockViewType != 0 && pPointingIcon->iSidRedrawSubdockContent == 0 && pParentDock != NULL)
1187 {
1188 cairo_dock_draw_subdock_content_on_icon (pPointingIcon, pParentDock);
1189 cairo_dock_redraw_icon (pPointingIcon);
1190 }
1191 }
1192
_update_WM_icons(CairoDock * pDock)1193 static gboolean _update_WM_icons (CairoDock *pDock)
1194 {
1195 cairo_dock_set_icons_geometry_for_window_manager (pDock);
1196 pDock->iSidUpdateWMIcons = 0;
1197 return FALSE;
1198 }
cairo_dock_trigger_set_WM_icons_geometry(CairoDock * pDock)1199 void cairo_dock_trigger_set_WM_icons_geometry (CairoDock *pDock)
1200 {
1201 if (pDock->iSidUpdateWMIcons == 0)
1202 {
1203 pDock->iSidUpdateWMIcons = g_idle_add ((GSourceFunc) _update_WM_icons, pDock);
1204 }
1205 }
1206
cairo_dock_resize_icon_in_dock(Icon * pIcon,CairoDock * pDock)1207 void cairo_dock_resize_icon_in_dock (Icon *pIcon, CairoDock *pDock) // resize the icon according to the requested size previously set on the icon.
1208 {
1209 cairo_dock_set_icon_size_in_dock (pDock, pIcon);
1210
1211 cairo_dock_load_icon_image (pIcon, CAIRO_CONTAINER (pDock)); // handles the applet's context
1212
1213 if (cairo_dock_get_icon_data_renderer (pIcon) != NULL)
1214 cairo_dock_reload_data_renderer_on_icon (pIcon, CAIRO_CONTAINER (pDock));
1215
1216 cairo_dock_trigger_update_dock_size (pDock);
1217 gtk_widget_queue_draw (pDock->container.pWidget);
1218 }
1219
1220
1221 ///////////////////////
1222 /// DOCK BACKGROUND ///
1223 ///////////////////////
1224
_cairo_dock_make_stripes_background(int iWidth,int iHeight,GldiColor * fStripesColorBright,GldiColor * fStripesColorDark,int iNbStripes,double fStripesWidth,double fStripesAngle)1225 static cairo_surface_t *_cairo_dock_make_stripes_background (int iWidth, int iHeight, GldiColor *fStripesColorBright, GldiColor *fStripesColorDark, int iNbStripes, double fStripesWidth, double fStripesAngle)
1226 {
1227 cairo_pattern_t *pStripesPattern;
1228 if (fabs (fStripesAngle) != 90)
1229 pStripesPattern = cairo_pattern_create_linear (0.0f,
1230 0.0f,
1231 iWidth,
1232 iWidth * tan (fStripesAngle * G_PI/180.));
1233 else
1234 pStripesPattern = cairo_pattern_create_linear (0.0f,
1235 0.0f,
1236 0.,
1237 (fStripesAngle == 90) ? iHeight : - iHeight);
1238 g_return_val_if_fail (cairo_pattern_status (pStripesPattern) == CAIRO_STATUS_SUCCESS, NULL);
1239
1240 cairo_pattern_set_extend (pStripesPattern, CAIRO_EXTEND_REPEAT);
1241
1242 if (iNbStripes > 0)
1243 {
1244 gdouble fStep;
1245 int i;
1246 for (i = 0; i < iNbStripes+1; i ++)
1247 {
1248 fStep = (double)i / iNbStripes;
1249 cairo_pattern_add_color_stop_rgba (pStripesPattern,
1250 fStep - fStripesWidth / 2.,
1251 fStripesColorBright->rgba.red,
1252 fStripesColorBright->rgba.green,
1253 fStripesColorBright->rgba.blue,
1254 fStripesColorBright->rgba.alpha);
1255 cairo_pattern_add_color_stop_rgba (pStripesPattern,
1256 fStep,
1257 fStripesColorDark->rgba.red,
1258 fStripesColorDark->rgba.green,
1259 fStripesColorDark->rgba.blue,
1260 fStripesColorDark->rgba.alpha);
1261 cairo_pattern_add_color_stop_rgba (pStripesPattern,
1262 fStep + fStripesWidth / 2.,
1263 fStripesColorBright->rgba.red,
1264 fStripesColorBright->rgba.green,
1265 fStripesColorBright->rgba.blue,
1266 fStripesColorBright->rgba.alpha);
1267 }
1268 }
1269 else
1270 {
1271 cairo_pattern_add_color_stop_rgba (pStripesPattern,
1272 0.,
1273 fStripesColorDark->rgba.red,
1274 fStripesColorDark->rgba.green,
1275 fStripesColorDark->rgba.blue,
1276 fStripesColorDark->rgba.alpha);
1277 cairo_pattern_add_color_stop_rgba (pStripesPattern,
1278 1.,
1279 fStripesColorBright->rgba.red,
1280 fStripesColorBright->rgba.green,
1281 fStripesColorBright->rgba.blue,
1282 fStripesColorBright->rgba.alpha);
1283 }
1284
1285 cairo_surface_t *pNewSurface = cairo_dock_create_blank_surface (
1286 iWidth,
1287 iHeight);
1288 cairo_t *pImageContext = cairo_create (pNewSurface);
1289 cairo_set_source (pImageContext, pStripesPattern);
1290 cairo_paint (pImageContext);
1291
1292 cairo_pattern_destroy (pStripesPattern);
1293 cairo_destroy (pImageContext);
1294
1295 return pNewSurface;
1296 }
_cairo_dock_load_default_background(CairoDockImageBuffer * pImage,int iWidth,int iHeight)1297 static void _cairo_dock_load_default_background (CairoDockImageBuffer *pImage, int iWidth, int iHeight)
1298 {
1299 cd_debug ("%s (%s, %d, %dx%d)", __func__, myDocksParam.cBackgroundImageFile, myDocksParam.bBackgroundImageRepeat, iWidth, iHeight);
1300 if (myDocksParam.bUseDefaultColors)
1301 {
1302 cairo_surface_t *pBgSurface = cairo_dock_create_blank_surface (
1303 iWidth,
1304 iHeight);
1305 cairo_t *pImageContext = cairo_create (pBgSurface);
1306
1307 /* Add a small vertical gradation to the bg color, it looks better than
1308 * a completely monochrome background. At the top is the original color
1309 * which connects nicely with other items (labels, menus, dialogs)
1310 */
1311 GldiColor bg_color, bg_color2;
1312 gldi_style_color_get (GLDI_COLOR_BG, &bg_color);
1313 gldi_style_color_shade (&bg_color, GLDI_COLOR_SHADE_LIGHT, &bg_color2);
1314
1315 cairo_pattern_t *pattern = cairo_pattern_create_linear (0, 0, 0, iHeight);
1316 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_NONE);
1317 cairo_pattern_add_color_stop_rgba (pattern,
1318 1.,
1319 bg_color.rgba.red, bg_color.rgba.green, bg_color.rgba.blue, bg_color.rgba.alpha); // this will be at the bottom of the dock
1320 cairo_pattern_add_color_stop_rgba (pattern,
1321 0.5,
1322 bg_color2.rgba.red, bg_color2.rgba.green, bg_color2.rgba.blue, bg_color2.rgba.alpha); // middle
1323 cairo_pattern_add_color_stop_rgba (pattern,
1324 0.,
1325 bg_color.rgba.red, bg_color.rgba.green, bg_color.rgba.blue, bg_color.rgba.alpha); // and this is at the top
1326 cairo_set_source (pImageContext, pattern);
1327 ///gldi_style_colors_set_bg_color (pImageContext);
1328
1329 cairo_pattern_destroy (pattern);
1330 cairo_paint (pImageContext);
1331 cairo_destroy (pImageContext);
1332 cairo_dock_load_image_buffer_from_surface (pImage,
1333 pBgSurface,
1334 iWidth,
1335 iHeight);
1336 }
1337 else if (myDocksParam.cBackgroundImageFile != NULL)
1338 {
1339 if (myDocksParam.bBackgroundImageRepeat)
1340 {
1341 cairo_surface_t *pBgSurface = cairo_dock_create_surface_from_pattern (myDocksParam.cBackgroundImageFile,
1342 iWidth,
1343 iHeight,
1344 myDocksParam.fBackgroundImageAlpha);
1345 cairo_dock_load_image_buffer_from_surface (pImage,
1346 pBgSurface,
1347 iWidth,
1348 iHeight);
1349 }
1350 else
1351 {
1352 cairo_dock_load_image_buffer_full (pImage,
1353 myDocksParam.cBackgroundImageFile,
1354 iWidth,
1355 iHeight,
1356 CAIRO_DOCK_FILL_SPACE,
1357 myDocksParam.fBackgroundImageAlpha);
1358 }
1359 }
1360 if (pImage->pSurface == NULL)
1361 {
1362 cairo_surface_t *pBgSurface = _cairo_dock_make_stripes_background (
1363 iWidth,
1364 iHeight,
1365 &myDocksParam.fStripesColorBright,
1366 &myDocksParam.fStripesColorDark,
1367 myDocksParam.iNbStripes,
1368 myDocksParam.fStripesWidth,
1369 myDocksParam.fStripesAngle);
1370 cairo_dock_load_image_buffer_from_surface (pImage,
1371 pBgSurface,
1372 iWidth,
1373 iHeight);
1374 }
1375 }
1376
cairo_dock_load_dock_background(CairoDock * pDock)1377 void cairo_dock_load_dock_background (CairoDock *pDock)
1378 {
1379 cairo_dock_unload_image_buffer (&pDock->backgroundBuffer);
1380
1381 int iWidth = pDock->iDecorationsWidth;
1382 int iHeight = pDock->iDecorationsHeight;
1383
1384 if (pDock->bGlobalBg || pDock->iRefCount > 0)
1385 {
1386 _cairo_dock_load_default_background (&pDock->backgroundBuffer, iWidth, iHeight);
1387 }
1388 else if (pDock->cBgImagePath != NULL)
1389 {
1390 cairo_dock_load_image_buffer (&pDock->backgroundBuffer, pDock->cBgImagePath, iWidth, iHeight, CAIRO_DOCK_FILL_SPACE);
1391 }
1392 if (pDock->backgroundBuffer.pSurface == NULL)
1393 {
1394 cairo_surface_t *pSurface = _cairo_dock_make_stripes_background (iWidth, iHeight, &pDock->fBgColorBright, &pDock->fBgColorDark, 0, 0., 90);
1395 cairo_dock_load_image_buffer_from_surface (&pDock->backgroundBuffer, pSurface, iWidth, iHeight);
1396 }
1397 gtk_widget_queue_draw (pDock->container.pWidget);
1398 }
1399
_load_background_idle(CairoDock * pDock)1400 static gboolean _load_background_idle (CairoDock *pDock)
1401 {
1402 cairo_dock_load_dock_background (pDock);
1403
1404 pDock->iSidLoadBg = 0;
1405 return FALSE;
1406 }
cairo_dock_trigger_load_dock_background(CairoDock * pDock)1407 void cairo_dock_trigger_load_dock_background (CairoDock *pDock)
1408 {
1409 if (pDock->iDecorationsWidth == pDock->backgroundBuffer.iWidth && pDock->iDecorationsHeight == pDock->backgroundBuffer.iHeight) // mise a jour inutile.
1410 return;
1411 if (pDock->iSidLoadBg == 0)
1412 pDock->iSidLoadBg = g_idle_add ((GSourceFunc)_load_background_idle, pDock);
1413 }
1414
1415
cairo_dock_make_preview(CairoDock * pDock,const gchar * cPreviewPath)1416 void cairo_dock_make_preview (CairoDock *pDock, const gchar *cPreviewPath)
1417 {
1418 if (pDock && pDock->pRenderer)
1419 {
1420 // place the mouse in the middle of the dock and update the icons position
1421 pDock->container.iMouseX = pDock->container.iWidth/2;
1422 pDock->container.iMouseY = 1;
1423 cairo_dock_calculate_dock_icons (pDock);
1424
1425 // dump the context into a cairo-surface
1426 cairo_surface_t *pSurface;
1427 int w = (pDock->container.bIsHorizontal ? pDock->container.iWidth : pDock->container.iHeight); // iActiveWidth
1428 int h = (pDock->container.bIsHorizontal ? pDock->container.iHeight : pDock->container.iWidth); // iActiveHeight
1429 GLubyte *glbuffer = NULL;
1430 if (g_bUseOpenGL)
1431 {
1432 if (gldi_gl_container_begin_draw (CAIRO_CONTAINER (pDock)))
1433 {
1434 pDock->pRenderer->render_opengl (pDock);
1435 }
1436 int s = 4; // 4 channels of 1 byte each (rgba).
1437 GLubyte *buffer = (GLubyte *) g_malloc (w * h * s);
1438 glbuffer = (GLubyte *) g_malloc (w * h * s);
1439
1440 glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)buffer);
1441
1442 // make upside down
1443 int x, y;
1444 for (y=0; y<h; y++) {
1445 for (x=0; x<w*s; x++) {
1446 glbuffer[y * s * w + x] = buffer[(h - y - 1) * w * s + x];
1447 }
1448 }
1449
1450 int iStride = w * s; // number of bytes between the beginning of the 2 lines
1451 pSurface = cairo_image_surface_create_for_data ((guchar *)glbuffer,
1452 CAIRO_FORMAT_ARGB32,
1453 w,
1454 h,
1455 iStride);
1456
1457 g_free (buffer);
1458 }
1459 else
1460 {
1461 pSurface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
1462 w,
1463 h);
1464 cairo_t *pCairoContext = cairo_create (pSurface);
1465 pDock->pRenderer->render (pCairoContext, pDock);
1466 cairo_destroy (pCairoContext);
1467 }
1468 // dump the surface into a PNG
1469 if (!pDock->container.bIsHorizontal)
1470 {
1471 cairo_t *pCairoContext = cairo_create (pSurface);
1472 cairo_translate (pCairoContext, w/2, h/2);
1473 cairo_rotate (pCairoContext, -G_PI/2);
1474 cairo_translate (pCairoContext, -h/2, -w/2);
1475 cairo_destroy (pCairoContext);
1476 }
1477
1478 cairo_surface_write_to_png (pSurface, cPreviewPath);
1479 cairo_surface_destroy (pSurface);
1480 g_free (glbuffer);
1481 }
1482 }
1483