1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23
24 #include <GL/gl.h>
25 #include <GL/glu.h>
26
27 #include "gldi-config.h"
28 #include "cairo-dock-icon-factory.h"
29 #include "cairo-dock-icon-facility.h"
30 #include "cairo-dock-container.h"
31 #include "cairo-dock-image-buffer.h"
32 #include "cairo-dock-draw.h"
33 #include "cairo-dock-draw-opengl.h"
34 #include "cairo-dock-log.h"
35 #include "cairo-dock-desklet-factory.h"
36 #include "cairo-dock-dock-manager.h"
37 #include "cairo-dock-dock-facility.h"
38 #include "cairo-dock-backends-manager.h"
39 #include "cairo-dock-surface-factory.h"
40 #include "cairo-dock-animations.h" // cairo_dock_launch_animation
41 #include "cairo-dock-launcher-manager.h" // cairo_dock_search_icon_s_path
42 #include "cairo-dock-windows-manager.h" // gldi_windows_get_active
43 #include "cairo-dock-desktop-manager.h"
44 #include "cairo-dock-style-manager.h"
45 #include "cairo-dock-dialog-manager.h"
46 #include "cairo-dock-dialog-factory.h"
47
48 extern gboolean g_bUseOpenGL;
49 extern CairoDock *g_pMainDock;
50
51
_compute_dialog_sizes(CairoDialog * pDialog)52 static void _compute_dialog_sizes (CairoDialog *pDialog)
53 {
54 pDialog->iMessageWidth = pDialog->iIconSize + pDialog->iTextWidth + (pDialog->iTextWidth != 0 ? 2 : 0) * CAIRO_DIALOG_TEXT_MARGIN - pDialog->iIconOffsetX; // icone + marge + texte + marge.
55 pDialog->iMessageHeight = MAX (pDialog->iIconSize - pDialog->iIconOffsetY, pDialog->iTextHeight) + (pDialog->pInteractiveWidget != NULL ? CAIRO_DIALOG_VGAP : 0); // (icone/texte + marge) + widget + (marge + boutons) + pointe.
56
57 if (pDialog->pButtons != NULL)
58 {
59 pDialog->iButtonsWidth = pDialog->iNbButtons * myDialogsParam.iDialogButtonWidth + (pDialog->iNbButtons - 1) * CAIRO_DIALOG_BUTTON_GAP + 2 * CAIRO_DIALOG_TEXT_MARGIN; // marge + bouton1 + ecart + bouton2 + marge.
60 pDialog->iButtonsHeight = CAIRO_DIALOG_VGAP + myDialogsParam.iDialogButtonHeight; // il y'a toujours quelque chose au-dessus (texte et/ou widget)
61 }
62
63 pDialog->iBubbleWidth = MAX (pDialog->iInteractiveWidth, MAX (pDialog->iButtonsWidth, MAX (pDialog->iMessageWidth, pDialog->iMinFrameWidth)));
64 pDialog->iBubbleHeight = pDialog->iMessageHeight + pDialog->iInteractiveHeight + pDialog->iButtonsHeight;
65 if (pDialog->iBubbleWidth == 0) // precaution.
66 pDialog->iBubbleWidth = 20;
67 if (pDialog->iBubbleHeight == 0)
68 pDialog->iBubbleHeight = 10;
69
70 pDialog->iComputedWidth = pDialog->iLeftMargin + pDialog->iBubbleWidth + pDialog->iRightMargin;
71 pDialog->iComputedHeight = pDialog->iTopMargin + pDialog->iBubbleHeight + pDialog->iBottomMargin + pDialog->iMinBottomGap; // all included.
72
73 pDialog->container.iWidth = pDialog->iComputedWidth;
74 pDialog->container.iHeight = pDialog->iComputedHeight;
75 }
76
on_expose_dialog(G_GNUC_UNUSED GtkWidget * pWidget,cairo_t * pCairoContext,CairoDialog * pDialog)77 static gboolean on_expose_dialog (G_GNUC_UNUSED GtkWidget *pWidget, cairo_t *pCairoContext, CairoDialog *pDialog)
78 {
79 //g_print ("%s (%dx%d ; %d;%d)\n", __func__, pDialog->container.iWidth, pDialog->container.iHeight, pExpose->area.x, pExpose->area.y);
80 /* int x, y;
81 // OpenGL renderers are not ready for dialogs.
82 if (g_bUseOpenGL && (pDialog->pDecorator == NULL || pDialog->pDecorator->render_opengl != NULL) && (pDialog->pRenderer == NULL || pDialog->pRenderer->render_opengl != NULL))
83 {
84 if (! gldi_glx_begin_draw_container (CAIRO_CONTAINER (pDialog)))
85 return FALSE;
86
87 if (pDialog->pDecorator != NULL && pDialog->pDecorator->render_opengl != NULL)
88 {
89 glPushMatrix ();
90 pDialog->pDecorator->render_opengl (pDialog);
91 glPopMatrix ();
92 }
93
94 gldi_object_notify (pDialog, NOTIFICATION_RENDER, pDialog, NULL);
95
96 gldi_glx_end_draw_container (CAIRO_CONTAINER (pDialog));
97 }
98 else
99 {*/
100 cairo_dock_init_drawing_context_on_container (CAIRO_CONTAINER (pDialog), pCairoContext);
101
102 if (pDialog->pDecorator != NULL)
103 {
104 cairo_save (pCairoContext);
105 pDialog->pDecorator->render (pCairoContext, pDialog);
106 cairo_restore (pCairoContext);
107 }
108
109 gldi_object_notify (pDialog, NOTIFICATION_RENDER, pDialog, pCairoContext);
110 //}
111 return FALSE;
112 }
113
on_expose_dialog_after(G_GNUC_UNUSED GtkWidget * pWidget,cairo_t * pCairoContext,CairoDialog * pDialog)114 static gboolean on_expose_dialog_after (G_GNUC_UNUSED GtkWidget *pWidget, cairo_t *pCairoContext, CairoDialog *pDialog)
115 {
116 if (pDialog->fAppearanceCounter < 1.) // modify the opacity after the interaction widget has been drawn by GTK.
117 {
118 double fAlpha = pDialog->fAppearanceCounter * pDialog->fAppearanceCounter;
119 cairo_rectangle (pCairoContext,
120 0,
121 0,
122 pDialog->container.iWidth,
123 pDialog->container.iHeight);
124 cairo_set_line_width (pCairoContext, 0);
125 cairo_set_operator (pCairoContext, CAIRO_OPERATOR_DEST_OUT);
126 cairo_set_source_rgba (pCairoContext, 0.0, 0.0, 0.0, 1. - fAlpha);
127 cairo_fill (pCairoContext);
128 }
129 return FALSE;
130 }
131
_cairo_dock_set_dialog_input_shape(CairoDialog * pDialog)132 static void _cairo_dock_set_dialog_input_shape (CairoDialog *pDialog)
133 {
134 if (pDialog->pShapeBitmap != NULL)
135 cairo_region_destroy (pDialog->pShapeBitmap);
136
137 pDialog->pShapeBitmap = gldi_container_create_input_shape (CAIRO_CONTAINER (pDialog),
138 0,
139 0,
140 1,
141 1); // workaround a bug in X with fully transparent window => let 1 pixel ON.
142
143 gldi_container_set_input_shape (CAIRO_CONTAINER (pDialog), pDialog->pShapeBitmap);
144 }
145
on_configure_dialog(G_GNUC_UNUSED GtkWidget * pWidget,GdkEventConfigure * pEvent,CairoDialog * pDialog)146 static gboolean on_configure_dialog (G_GNUC_UNUSED GtkWidget* pWidget,
147 GdkEventConfigure* pEvent,
148 CairoDialog *pDialog)
149 {
150 //g_print ("%s (%dx%d, %d;%d) [%d]\n", __func__, pEvent->width, pEvent->height, pEvent->x, pEvent->y, pDialog->bPositionForced);
151 if (pEvent->width <= CAIRO_DIALOG_MIN_SIZE && pEvent->height <= CAIRO_DIALOG_MIN_SIZE && ! pDialog->bNoInput)
152 {
153 pDialog->container.bInside = FALSE;
154 return FALSE;
155 }
156
157 //\____________ get dialog size and position.
158 int iPrevWidth = pDialog->container.iWidth, iPrevHeight = pDialog->container.iHeight;
159 pDialog->container.iWidth = pEvent->width;
160 pDialog->container.iHeight = pEvent->height;
161 pDialog->container.iWindowPositionX = pEvent->x;
162 pDialog->container.iWindowPositionY = pEvent->y;
163
164 //\____________ if an interactive widget is present, internal sizes may have changed.
165 if (pDialog->pInteractiveWidget != NULL)
166 {
167 int w = pDialog->iInteractiveWidth, h = pDialog->iInteractiveHeight;
168 GtkRequisition requisition;
169 gtk_widget_get_preferred_size (pDialog->pInteractiveWidget, &requisition, NULL);
170 pDialog->iInteractiveWidth = requisition.width;
171 pDialog->iInteractiveHeight = requisition.height;
172 //g_print (" pInteractiveWidget : %dx%d\n", pDialog->iInteractiveWidth, pDialog->iInteractiveHeight);
173 _compute_dialog_sizes (pDialog);
174
175 if (w != pDialog->iInteractiveWidth || h != pDialog->iInteractiveHeight)
176 {
177 gldi_dialogs_replace_all ();
178 /*Icon *pIcon = pDialog->pIcon;
179 if (pIcon != NULL)
180 {
181 GldiContainer *pContainer = cairo_dock_search_container_from_icon (pIcon);
182 cairo_dock_place_dialog (pDialog, pContainer);
183 }*/
184 }
185 }
186 //g_print ("dialog size: %dx%d / %dx%d\n", pEvent->width, pEvent->height, pDialog->iComputedWidth, pDialog->iComputedHeight);
187
188 //\____________ set input shape if size has changed or if no shape yet.
189 if (pDialog->bNoInput && (iPrevWidth != pEvent->width || iPrevHeight != pEvent->height || ! pDialog->pShapeBitmap))
190 {
191 _cairo_dock_set_dialog_input_shape (pDialog);
192 pDialog->container.bInside = FALSE;
193 }
194
195 //\____________ force position for buggy WM (Compiz).
196 if (pDialog->iComputedWidth == pEvent->width && pDialog->iComputedHeight == pEvent->height && (pEvent->y != pDialog->iComputedPositionY || pEvent->x != pDialog->iComputedPositionX) && pDialog->bPositionForced == 3)
197 {
198 pDialog->container.bInside = FALSE;
199 cd_debug ("force to %d;%d", pDialog->iComputedPositionX, pDialog->iComputedPositionY);
200 /*gtk_window_move (GTK_WINDOW (pDialog->container.pWidget),
201 pDialog->iComputedPositionX,
202 pDialog->iComputedPositionY);
203 */pDialog->bPositionForced ++;
204 }
205
206 gtk_widget_queue_draw (pDialog->container.pWidget); // les widgets internes peuvent avoir changer de taille sans que le dialogue n'en ait change, il faut donc redessiner tout le temps.
207
208 return FALSE;
209 }
210
on_unmap_dialog(GtkWidget * pWidget,G_GNUC_UNUSED GdkEvent * pEvent,CairoDialog * pDialog)211 static gboolean on_unmap_dialog (GtkWidget* pWidget,
212 G_GNUC_UNUSED GdkEvent *pEvent,
213 CairoDialog *pDialog)
214 {
215 //g_print ("unmap dialog (bAllowMinimize:%d, visible:%d)\n", pDialog->bAllowMinimize, GTK_WIDGET_VISIBLE (pWidget));
216 if (! pDialog->bAllowMinimize) // it's an unexpected unmap event
217 {
218 if (pDialog->pUnmapTimer) // see if it happened just after an event that we expected
219 {
220 double fElapsedTime = g_timer_elapsed (pDialog->pUnmapTimer, NULL);
221 //g_print ("fElapsedTime : %fms\n", fElapsedTime);
222 if (fElapsedTime < .2) // it's a 2nd unmap event just after the first one, ignore it, it's just some noise from the WM
223 return TRUE;
224 }
225 gtk_window_present (GTK_WINDOW (pWidget)); // counter it, we don't want dialogs to be hidden
226 }
227 else // expected event, it's an unmap that we triggered with 'gldi_dialog_hide', so let pass it
228 {
229 pDialog->bAllowMinimize = FALSE;
230 if (pDialog->pUnmapTimer != NULL)
231 g_timer_destroy (pDialog->pUnmapTimer);
232 pDialog->pUnmapTimer = g_timer_new (); // remember the time it arrived
233 }
234 return TRUE; // stops other handlers from being invoked for the event.
235 }
236
on_map_dialog(G_GNUC_UNUSED GtkWidget * pWidget,G_GNUC_UNUSED GdkEvent * pEvent,CairoDialog * pDialog)237 static gboolean on_map_dialog (G_GNUC_UNUSED GtkWidget* pWidget,
238 G_GNUC_UNUSED GdkEvent *pEvent,
239 CairoDialog *pDialog)
240 {
241 if (pDialog->pInteractiveWidget)
242 {
243 gldi_container_present (CAIRO_CONTAINER (pDialog));
244 }
245 return FALSE;
246 }
247
on_button_press_widget(G_GNUC_UNUSED GtkWidget * widget,GdkEventButton * pButton,CairoDialog * pDialog)248 static gboolean on_button_press_widget (G_GNUC_UNUSED GtkWidget *widget,
249 GdkEventButton *pButton,
250 CairoDialog *pDialog)
251 {
252 cd_debug ("press button on widget");
253 // memorize the time when the user clicked on the widget.
254 pDialog->iButtonPressTime = pButton->time;
255 return FALSE;
256 }
257
_cairo_dock_add_dialog_internal_box(CairoDialog * pDialog,int iWidth,int iHeight,gboolean bCanResize)258 static GtkWidget *_cairo_dock_add_dialog_internal_box (CairoDialog *pDialog, int iWidth, int iHeight, gboolean bCanResize)
259 {
260 GtkWidget *pBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
261 if (iWidth != 0 && iHeight != 0)
262 g_object_set (pBox, "height-request", iHeight, "width-request", iWidth, NULL);
263 else if (iWidth != 0)
264 g_object_set (pBox, "width-request", iWidth, NULL);
265 else if (iHeight != 0)
266 g_object_set (pBox, "height-request", iHeight, NULL);
267 gtk_box_pack_start (GTK_BOX (pDialog->pWidgetLayout),
268 pBox,
269 bCanResize,
270 bCanResize,
271 0);
272 return pBox;
273 }
274
_cairo_dock_create_dialog_text_surface(const gchar * cText,gboolean bUseMarkup,int * iTextWidth,int * iTextHeight)275 static cairo_surface_t *_cairo_dock_create_dialog_text_surface (const gchar *cText, gboolean bUseMarkup, int *iTextWidth, int *iTextHeight)
276 {
277 if (cText == NULL)
278 return NULL;
279
280 myDialogsParam.dialogTextDescription.bUseMarkup = bUseMarkup; // slight optimization, rather than duplicating the TextDescription each time.
281 cairo_surface_t *pSurface = cairo_dock_create_surface_from_text (cText,
282 &myDialogsParam.dialogTextDescription,
283 iTextWidth,
284 iTextHeight);
285 myDialogsParam.dialogTextDescription.bUseMarkup = FALSE; // by default
286 return pSurface;
287 }
288
_cairo_dock_create_dialog_icon_surface(const gchar * cImageFilePath,Icon * pIcon,int iDesiredSize,int * iIconSize)289 static cairo_surface_t *_cairo_dock_create_dialog_icon_surface (const gchar *cImageFilePath, Icon *pIcon, int iDesiredSize, int *iIconSize)
290 {
291 if (cImageFilePath == NULL)
292 return NULL;
293 if (iDesiredSize == 0)
294 iDesiredSize = myDialogsParam.iDialogIconSize;
295 cairo_surface_t *pIconBuffer = NULL;
296 if (strcmp (cImageFilePath, "same icon") == 0)
297 {
298 if (pIcon && pIcon->image.pSurface)
299 {
300 int iWidth, iHeight;
301 cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
302 pIconBuffer = cairo_dock_duplicate_surface (pIcon->image.pSurface,
303 iWidth, iHeight,
304 iDesiredSize, iDesiredSize);
305 }
306 else if (pIcon && pIcon->cFileName)
307 {
308 pIconBuffer = cairo_dock_create_surface_from_image_simple (pIcon->cFileName,
309 iDesiredSize,
310 iDesiredSize);
311 }
312 }
313 else
314 {
315 pIconBuffer = cairo_dock_create_surface_from_image_simple (cImageFilePath,
316 iDesiredSize,
317 iDesiredSize);
318 }
319 if (pIconBuffer != NULL)
320 *iIconSize = iDesiredSize;
321 return pIconBuffer;
322 }
323
_animation_loop(GldiContainer * pContainer)324 static gboolean _animation_loop (GldiContainer *pContainer)
325 {
326 CairoDialog *pDialog = CAIRO_DIALOG (pContainer);
327 gboolean bContinue = FALSE;
328 gboolean bUpdateSlowAnimation = FALSE;
329 pContainer->iAnimationStep ++;
330 if (pContainer->iAnimationStep * pContainer->iAnimationDeltaT >= CAIRO_DOCK_MIN_SLOW_DELTA_T)
331 {
332 bUpdateSlowAnimation = TRUE;
333 pContainer->iAnimationStep = 0;
334 pContainer->bKeepSlowAnimation = FALSE;
335 }
336
337 if (pDialog->fAppearanceCounter < 1)
338 {
339 pDialog->fAppearanceCounter += .08;
340 if (pDialog->fAppearanceCounter > .99)
341 {
342 pDialog->fAppearanceCounter = 1.;
343 }
344 else
345 {
346 bContinue = TRUE;
347 }
348 }
349
350 if (bUpdateSlowAnimation)
351 {
352 gldi_object_notify (pDialog, NOTIFICATION_UPDATE_SLOW, pDialog, &pContainer->bKeepSlowAnimation);
353 }
354
355 gldi_object_notify (pDialog, NOTIFICATION_UPDATE, pDialog, &bContinue);
356
357 cairo_dock_redraw_container (CAIRO_CONTAINER (pDialog));
358 if (! bContinue && ! pContainer->bKeepSlowAnimation)
359 {
360 pContainer->iSidGLAnimation = 0;
361 return FALSE;
362 }
363 else
364 return TRUE;
365 }
366
gldi_dialog_init_internals(CairoDialog * pDialog,CairoDialogAttr * pAttribute)367 void gldi_dialog_init_internals (CairoDialog *pDialog, CairoDialogAttr *pAttribute)
368 {
369 pDialog->container.iface.animation_loop = _animation_loop;
370
371 //\________________ set up the window
372 GtkWidget *pWindow = pDialog->container.pWidget;
373 gtk_window_set_title (GTK_WINDOW (pWindow), "cairo-dock-dialog");
374 if (! pAttribute->pInteractiveWidget && ! pAttribute->pActionFunc) // not an interactive dialog
375 gtk_window_set_type_hint (GTK_WINDOW (pDialog->container.pWidget), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); // pour ne pas prendre le focus.
376
377 gtk_widget_add_events (pWindow, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
378 gtk_window_resize (GTK_WINDOW (pWindow), CAIRO_DIALOG_MIN_SIZE, CAIRO_DIALOG_MIN_SIZE);
379 gtk_window_set_keep_above (GTK_WINDOW (pWindow), TRUE);
380
381 pDialog->pIcon = pAttribute->pIcon;
382 if (pAttribute->bForceAbove) // try to force it above other windows (with most WM, it will still stay below fullscreen windows).
383 {
384 gtk_window_set_keep_above (GTK_WINDOW (pDialog->container.pWidget), TRUE);
385 gtk_window_set_type_hint (GTK_WINDOW (pDialog->container.pWidget), GDK_WINDOW_TYPE_HINT_DOCK); // should be called before the window becomes visible
386 }
387
388 //\________________ load the message
389 if (pAttribute->cText != NULL)
390 {
391 pDialog->cText = g_strdup (pAttribute->cText); // it may be a const string, so duplicate it
392 pDialog->pTextBuffer = _cairo_dock_create_dialog_text_surface (pAttribute->cText,
393 pAttribute->bUseMarkup,
394 &pDialog->iTextWidth, &pDialog->iTextHeight);
395 ///pDialog->iTextTexture = cairo_dock_create_texture_from_surface (pDialog->pTextBuffer);
396 }
397 pDialog->bUseMarkup = pAttribute->bUseMarkup; // remember this attribute, in case another text is set (with cairo_dock_set_dialog_message).
398
399 //\________________ load the icon
400 if (pAttribute->cImageFilePath != NULL)
401 {
402 pDialog->pIconBuffer = _cairo_dock_create_dialog_icon_surface (pAttribute->cImageFilePath, pAttribute->pIcon, pAttribute->iIconSize, &pDialog->iIconSize);
403 ///pDialog->iIconTexture = cairo_dock_create_texture_from_surface (pDialog->pIconBuffer);
404 }
405
406 //\________________ load the interactive widget
407 if (pAttribute->pInteractiveWidget != NULL)
408 {
409 pDialog->pInteractiveWidget = pAttribute->pInteractiveWidget;
410
411 GtkRequisition requisition;
412 gtk_widget_get_preferred_size (pAttribute->pInteractiveWidget, &requisition, NULL);
413 pDialog->iInteractiveWidth = requisition.width;
414 pDialog->iInteractiveHeight = requisition.height;
415 }
416
417 //\________________ load the buttons
418 pDialog->pUserData = pAttribute->pUserData;
419 pDialog->pFreeUserDataFunc = pAttribute->pFreeDataFunc;
420 if (pAttribute->cButtonsImage != NULL && pAttribute->pActionFunc != NULL)
421 {
422 int i;
423 for (i = 0; pAttribute->cButtonsImage[i] != NULL; i++);
424
425 pDialog->iNbButtons = i;
426 pDialog->action_on_answer = pAttribute->pActionFunc;
427 pDialog->pButtons = g_new0 (CairoDialogButton, pDialog->iNbButtons);
428 const gchar *cButtonImage;
429 for (i = 0; i < pDialog->iNbButtons; i++)
430 {
431 cButtonImage = pAttribute->cButtonsImage[i];
432 if (strcmp (cButtonImage, "ok") == 0)
433 {
434 pDialog->pButtons[i].iDefaultType = 1;
435 }
436 else if (strcmp (cButtonImage, "cancel") == 0)
437 {
438 pDialog->pButtons[i].iDefaultType = 0;
439 }
440 else
441 {
442 gchar *cButtonPath;
443 if (*cButtonImage != '/')
444 cButtonPath = cairo_dock_search_icon_s_path (cButtonImage,
445 MAX (myDialogsParam.iDialogButtonWidth, myDialogsParam.iDialogButtonHeight));
446 else
447 cButtonPath = (gchar*)cButtonImage;
448 pDialog->pButtons[i].pSurface = cairo_dock_create_surface_from_image_simple (cButtonPath,
449 myDialogsParam.iDialogButtonWidth,
450 myDialogsParam.iDialogButtonHeight);
451 if (cButtonPath != cButtonImage)
452 g_free (cButtonPath);
453 ///pDialog->pButtons[i].iTexture = cairo_dock_create_texture_from_surface (pDialog->pButtons[i].pSurface);
454 }
455 }
456 }
457 else
458 {
459 pDialog->bNoInput = pAttribute->bNoInput;
460 }
461
462 //\________________ set a decorator.
463 cairo_dock_set_dialog_decorator_by_name (pDialog, (pAttribute->cDecoratorName ? pAttribute->cDecoratorName : myDialogsParam.cDecoratorName));
464 if (pDialog->pDecorator != NULL)
465 pDialog->pDecorator->set_size (pDialog);
466
467 //\________________ Maintenant qu'on connait tout, on calcule les tailles des divers elements.
468 _compute_dialog_sizes (pDialog);
469 pDialog->container.iWidth = pDialog->iBubbleWidth + pDialog->iLeftMargin + pDialog->iRightMargin;
470 pDialog->container.iHeight = pDialog->iBubbleHeight + pDialog->iTopMargin + pDialog->iBottomMargin + pDialog->iMinBottomGap;
471
472 //\________________ On reserve l'espace pour les decorations.
473 GtkWidget *pMainHBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
474 gtk_container_add (GTK_CONTAINER (pDialog->container.pWidget), pMainHBox);
475 pDialog->pLeftPaddingBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
476 g_object_set (pDialog->pLeftPaddingBox, "width-request", pDialog->iLeftMargin, NULL);
477 gtk_box_pack_start (GTK_BOX (pMainHBox),
478 pDialog->pLeftPaddingBox,
479 FALSE,
480 FALSE,
481 0);
482
483 pDialog->pWidgetLayout = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
484 gtk_box_pack_start (GTK_BOX (pMainHBox),
485 pDialog->pWidgetLayout,
486 FALSE,
487 FALSE,
488 0);
489
490 pDialog->pRightPaddingBox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
491 g_object_set (pDialog->pRightPaddingBox, "width-request", pDialog->iRightMargin, NULL);
492 gtk_box_pack_start (GTK_BOX (pMainHBox),
493 pDialog->pRightPaddingBox,
494 FALSE,
495 FALSE,
496 0);
497
498 //\________________ On reserve l'espace pour les elements.
499 if (pDialog->container.bDirectionUp)
500 pDialog->pTopWidget = _cairo_dock_add_dialog_internal_box (pDialog, 0, pDialog->iTopMargin, FALSE);
501 else
502 pDialog->pTipWidget = _cairo_dock_add_dialog_internal_box (pDialog, 0, pDialog->iMinBottomGap + pDialog->iBottomMargin, TRUE);
503 if (pDialog->iMessageWidth != 0 && pDialog->iMessageHeight != 0)
504 {
505 pDialog->pMessageWidget = _cairo_dock_add_dialog_internal_box (pDialog, pDialog->iMessageWidth, pDialog->iMessageHeight, FALSE);
506 }
507 if (pDialog->pInteractiveWidget != NULL)
508 {
509 gtk_box_pack_start (GTK_BOX (pDialog->pWidgetLayout),
510 pDialog->pInteractiveWidget,
511 FALSE,
512 FALSE,
513 0);
514 gtk_window_present (GTK_WINDOW (pDialog->container.pWidget));
515 gtk_widget_grab_focus (pDialog->pInteractiveWidget);
516
517 // set a MenuItem style to the dialog, so that the interactive widget can use the style defined for menu-items (either from the GTK theme, or from our own .css), and therefore be well integrated into the dialog, as if it was inside a menu.
518 GtkStyleContext *ctx = gtk_widget_get_style_context (pDialog->pWidgetLayout);
519 gtk_style_context_add_class (ctx, myDialogsParam.bUseDefaultColors && myStyleParam.bUseSystemColors ? GTK_STYLE_CLASS_MENUITEM : "gldimenuitem");
520 }
521 if (pDialog->pButtons != NULL)
522 {
523 pDialog->pButtonsWidget = _cairo_dock_add_dialog_internal_box (pDialog, pDialog->iButtonsWidth, pDialog->iButtonsHeight, FALSE);
524 }
525 if (pDialog->container.bDirectionUp)
526 pDialog->pTipWidget = _cairo_dock_add_dialog_internal_box (pDialog, 0, pDialog->iMinBottomGap + pDialog->iBottomMargin, TRUE);
527 else
528 pDialog->pTopWidget = _cairo_dock_add_dialog_internal_box (pDialog, 0, pDialog->iTopMargin, TRUE);
529
530 gtk_widget_show_all (pDialog->container.pWidget);
531
532 //\________________ load the input shape.
533 if (pDialog->bNoInput)
534 {
535 _cairo_dock_set_dialog_input_shape (pDialog);
536 }
537
538 //\________________ connect the signals to the window
539 g_signal_connect (G_OBJECT (pDialog->container.pWidget),
540 "draw",
541 G_CALLBACK (on_expose_dialog),
542 pDialog);
543 g_signal_connect_after (G_OBJECT (pDialog->container.pWidget),
544 "draw",
545 G_CALLBACK (on_expose_dialog_after),
546 pDialog);
547 g_signal_connect (G_OBJECT (pDialog->container.pWidget),
548 "configure-event",
549 G_CALLBACK (on_configure_dialog),
550 pDialog);
551 g_signal_connect (G_OBJECT (pDialog->container.pWidget),
552 "unmap-event",
553 G_CALLBACK (on_unmap_dialog),
554 pDialog); // prevent dialogs from being hidden (for instance by a 'show-desktop' event), because they might be modal
555 g_signal_connect (G_OBJECT (pDialog->container.pWidget),
556 "map-event",
557 G_CALLBACK (on_map_dialog),
558 pDialog); // some WM (like GS) prevent the focus to be taken, so we have to force it whenever the dialog is shown (creation or unhide).
559 if (pDialog->pInteractiveWidget != NULL && pDialog->pButtons == NULL) // the dialog has no button to be closed, so it can be closed by clicking on it. But some widget (like the GTK calendar) let pass the click to their parent (= the dialog), which then close it. To prevent this, we memorize the last click on the widget.
560 g_signal_connect (G_OBJECT (pDialog->pInteractiveWidget),
561 "button-press-event",
562 G_CALLBACK (on_button_press_widget),
563 pDialog);
564
565 cairo_dock_launch_animation (CAIRO_CONTAINER (pDialog));
566 }
567
gldi_dialog_new(CairoDialogAttr * pAttribute)568 CairoDialog *gldi_dialog_new (CairoDialogAttr *pAttribute)
569 {
570 if (!pAttribute->bForceAbove)
571 {
572 GldiWindowActor *pActiveAppli = gldi_windows_get_active ();
573 if (pActiveAppli && pActiveAppli->bIsFullScreen && gldi_window_is_on_current_desktop (pActiveAppli))
574 {
575 cd_debug ("skip dialog since current fullscreen window would mask it");
576 return NULL;
577 }
578 }
579 pAttribute->cattr.bNoOpengl = TRUE;
580 cd_debug ("%s (%s, %s, %x, %x, (%p;%p))", __func__, pAttribute->cText, pAttribute->cImageFilePath, pAttribute->pInteractiveWidget, pAttribute->pActionFunc, pAttribute->pIcon, pAttribute->pContainer);
581 return (CairoDialog*)gldi_object_new (&myDialogObjectMgr, pAttribute);
582 }
583
584
gldi_dialog_show(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,double fTimeLength,const gchar * cIconPath,GtkWidget * pInteractiveWidget,CairoDockActionOnAnswerFunc pActionFunc,gpointer data,GFreeFunc pFreeDataFunc)585 CairoDialog *gldi_dialog_show (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, double fTimeLength, const gchar *cIconPath, GtkWidget *pInteractiveWidget, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
586 {
587 if (pIcon != NULL && cairo_dock_icon_is_being_removed (pIcon)) // icone en cours de suppression.
588 {
589 cd_debug ("dialog skipped for %s (%.2f)", pIcon->cName, pIcon->fInsertRemoveFactor);
590 return NULL;
591 }
592
593 CairoDialogAttr attr;
594 memset (&attr, 0, sizeof (CairoDialogAttr));
595 attr.cText = (gchar *)cText;
596 attr.cImageFilePath = (gchar *)cIconPath;
597 attr.pInteractiveWidget = pInteractiveWidget;
598 attr.pActionFunc = pActionFunc;
599 attr.pUserData = data;
600 attr.pFreeDataFunc = pFreeDataFunc;
601 attr.iTimeLength = (int) fTimeLength;
602 const gchar *cDefaultActionButtons[3] = {"ok", "cancel", NULL};
603 if (pActionFunc != NULL)
604 attr.cButtonsImage = cDefaultActionButtons;
605 attr.pIcon = pIcon;
606 attr.pContainer = pContainer;
607
608 return gldi_dialog_new (&attr);
609 }
610
gldi_dialog_show_temporary_with_icon_printf(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,double fTimeLength,const gchar * cIconPath,...)611 CairoDialog *gldi_dialog_show_temporary_with_icon_printf (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, double fTimeLength, const gchar *cIconPath, ...)
612 {
613 g_return_val_if_fail (cText != NULL, NULL);
614 va_list args;
615 va_start (args, cIconPath);
616 gchar *cFullText = g_strdup_vprintf (cText, args);
617 CairoDialog *pDialog = gldi_dialog_show (cFullText, pIcon, pContainer, fTimeLength, cIconPath, NULL, NULL, NULL, NULL);
618 g_free (cFullText);
619 va_end (args);
620 return pDialog;
621 }
622
gldi_dialog_show_temporary_with_icon(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,double fTimeLength,const gchar * cIconPath)623 CairoDialog *gldi_dialog_show_temporary_with_icon (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, double fTimeLength, const gchar *cIconPath)
624 {
625 g_return_val_if_fail (cText != NULL, NULL);
626 return gldi_dialog_show (cText, pIcon, pContainer, fTimeLength, cIconPath, NULL, NULL, NULL, NULL);
627 }
628
gldi_dialog_show_temporary(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,double fTimeLength)629 CairoDialog *gldi_dialog_show_temporary (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, double fTimeLength)
630 {
631 g_return_val_if_fail (cText != NULL, NULL);
632 return gldi_dialog_show (cText, pIcon, pContainer, fTimeLength, NULL, NULL, NULL, NULL, NULL);
633 }
634
gldi_dialog_show_temporary_with_default_icon(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,double fTimeLength)635 CairoDialog *gldi_dialog_show_temporary_with_default_icon (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, double fTimeLength)
636 {
637 g_return_val_if_fail (cText != NULL, NULL);
638
639 const gchar *cIconPath = GLDI_SHARE_DATA_DIR"/"CAIRO_DOCK_ICON;
640
641 CairoDialogAttr attr;
642 memset (&attr, 0, sizeof (CairoDialogAttr));
643 attr.cText = cText;
644 attr.cImageFilePath = cIconPath;
645 attr.iTimeLength = (int) fTimeLength;
646 attr.pIcon = pIcon;
647 attr.pContainer = pContainer;
648
649 return gldi_dialog_new (&attr);
650 }
651
_cairo_dock_make_entry_for_dialog(const gchar * cTextForEntry)652 static inline GtkWidget *_cairo_dock_make_entry_for_dialog (const gchar *cTextForEntry)
653 {
654 GtkWidget *pWidget = gtk_entry_new ();
655 gtk_entry_set_has_frame (GTK_ENTRY (pWidget), FALSE);
656 g_object_set (pWidget, "width-request", CAIRO_DIALOG_MIN_ENTRY_WIDTH, NULL);
657 if (cTextForEntry != NULL)
658 gtk_entry_set_text (GTK_ENTRY (pWidget), cTextForEntry);
659 return pWidget;
660 }
_cairo_dock_make_hscale_for_dialog(double fValueForHScale,double fMaxValueForHScale)661 static inline GtkWidget *_cairo_dock_make_hscale_for_dialog (double fValueForHScale, double fMaxValueForHScale)
662 {
663 GtkWidget *pWidget = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, fMaxValueForHScale, fMaxValueForHScale / 100.);
664 gtk_scale_set_digits (GTK_SCALE (pWidget), 2);
665 gtk_range_set_value (GTK_RANGE (pWidget), fValueForHScale);
666
667 g_object_set (pWidget, "width-request", CAIRO_DIALOG_MIN_SCALE_WIDTH, NULL);
668 return pWidget;
669 }
670
gldi_dialog_show_with_question(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,const gchar * cIconPath,CairoDockActionOnAnswerFunc pActionFunc,gpointer data,GFreeFunc pFreeDataFunc)671 CairoDialog *gldi_dialog_show_with_question (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, const gchar *cIconPath, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
672 {
673 return gldi_dialog_show (cText, pIcon, pContainer, 0, cIconPath, NULL, pActionFunc, data, pFreeDataFunc);
674 }
675
gldi_dialog_show_with_entry(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,const gchar * cIconPath,const gchar * cTextForEntry,CairoDockActionOnAnswerFunc pActionFunc,gpointer data,GFreeFunc pFreeDataFunc)676 CairoDialog *gldi_dialog_show_with_entry (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, const gchar *cIconPath, const gchar *cTextForEntry, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
677 {
678 //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog (cTextForEntry, -1, -1);
679 GtkWidget *pWidget = _cairo_dock_make_entry_for_dialog (cTextForEntry);
680
681 return gldi_dialog_show (cText, pIcon, pContainer, 0, cIconPath, pWidget, pActionFunc, data, pFreeDataFunc);
682 }
683
gldi_dialog_show_with_value(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,const gchar * cIconPath,double fValue,double fMaxValue,CairoDockActionOnAnswerFunc pActionFunc,gpointer data,GFreeFunc pFreeDataFunc)684 CairoDialog *gldi_dialog_show_with_value (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, const gchar *cIconPath, double fValue, double fMaxValue, CairoDockActionOnAnswerFunc pActionFunc, gpointer data, GFreeFunc pFreeDataFunc)
685 {
686 fValue = MAX (0., fValue);
687 fValue = MIN (fMaxValue, fValue);
688 //GtkWidget *pWidget = cairo_dock_build_common_interactive_widget_for_dialog (NULL, fValue, 1.);
689 GtkWidget *pWidget = _cairo_dock_make_hscale_for_dialog (fValue, fMaxValue);
690
691 return gldi_dialog_show (cText, pIcon, pContainer, 0, cIconPath, pWidget, pActionFunc, data, pFreeDataFunc);
692 }
693
gldi_dialog_show_general_message(const gchar * cMessage,double fTimeLength)694 CairoDialog *gldi_dialog_show_general_message (const gchar *cMessage, double fTimeLength)
695 {
696 Icon *pIcon = gldi_icons_get_any_without_dialog ();
697 return gldi_dialog_show_temporary (cMessage, pIcon, CAIRO_CONTAINER (g_pMainDock), fTimeLength);
698 }
699
700
_cairo_dock_get_answer_from_dialog(int iClickedButton,G_GNUC_UNUSED GtkWidget * pInteractiveWidget,gpointer * data,CairoDialog * pDialog)701 static void _cairo_dock_get_answer_from_dialog (int iClickedButton, G_GNUC_UNUSED GtkWidget *pInteractiveWidget, gpointer *data, CairoDialog *pDialog)
702 {
703 cd_message ("%s (%d)", __func__, iClickedButton);
704 int *iAnswerBuffer = data[0];
705 // GMainLoop *pBlockingLoop = data[1];
706
707 gldi_dialog_steal_interactive_widget (pDialog); // le dialogue disparaitra apres cette fonction, mais le widget interactif doit rester.
708
709 *iAnswerBuffer = iClickedButton;
710 }
_on_free_blocking_dialog(gpointer * data)711 static void _on_free_blocking_dialog (gpointer *data)
712 {
713 GMainLoop *pBlockingLoop = data[1];
714 if (g_main_loop_is_running (pBlockingLoop))
715 g_main_loop_quit (pBlockingLoop);
716 }
gldi_dialog_show_and_wait(const gchar * cText,Icon * pIcon,GldiContainer * pContainer,const gchar * cIconPath,GtkWidget * pInteractiveWidget)717 int gldi_dialog_show_and_wait (const gchar *cText, Icon *pIcon, GldiContainer *pContainer, const gchar *cIconPath, GtkWidget *pInteractiveWidget)
718 {
719 int iClickedButton = -3;
720 GMainLoop *pBlockingLoop = g_main_loop_new (NULL, FALSE);
721 gpointer data[2] = {&iClickedButton, pBlockingLoop}; // it's useless to allocate 'data' because this function will wait for an answer
722
723 CairoDialog *pDialog = gldi_dialog_show (cText,
724 pIcon,
725 pContainer,
726 0.,
727 cIconPath,
728 pInteractiveWidget,
729 (CairoDockActionOnAnswerFunc)_cairo_dock_get_answer_from_dialog,
730 (gpointer) data,
731 (GFreeFunc)_on_free_blocking_dialog);
732
733 if (pDialog != NULL)
734 {
735 pDialog->fAppearanceCounter = 1.;
736 cd_debug ("Start the blocking loop...");
737 g_main_loop_run (pBlockingLoop);
738 cd_debug ("End of the blocking loop -> %d", iClickedButton);
739 }
740
741 g_main_loop_unref (pBlockingLoop);
742 return iClickedButton;
743 }
744
745
cairo_dock_steal_widget_from_its_container(GtkWidget * pWidget)746 GtkWidget *cairo_dock_steal_widget_from_its_container (GtkWidget *pWidget)
747 {
748 g_return_val_if_fail (pWidget != NULL, NULL);
749 GtkWidget *pContainer = gtk_widget_get_parent (pWidget);
750 if (pContainer != NULL)
751 {
752 g_object_ref (G_OBJECT (pWidget));
753 gtk_container_remove (GTK_CONTAINER (pContainer), pWidget);
754 }
755 return pWidget;
756 }
757
gldi_dialog_steal_interactive_widget(CairoDialog * pDialog)758 GtkWidget *gldi_dialog_steal_interactive_widget (CairoDialog *pDialog)
759 {
760 if (pDialog == NULL)
761 return NULL;
762
763 GtkWidget *pInteractiveWidget = pDialog->pInteractiveWidget;
764 if (pInteractiveWidget != NULL)
765 {
766 pInteractiveWidget = cairo_dock_steal_widget_from_its_container (pInteractiveWidget);
767 pDialog->pInteractiveWidget = NULL;
768
769 // if we were monitoring the click events on the widget, stop it.
770 g_signal_handlers_disconnect_matched (pInteractiveWidget,
771 G_SIGNAL_MATCH_FUNC,
772 0,
773 0,
774 NULL,
775 on_button_press_widget,
776 NULL);
777 }
778 return pInteractiveWidget;
779 }
780
_redraw_icon_surface(CairoDialog * pDialog)781 static void _redraw_icon_surface (CairoDialog *pDialog)
782 {
783 if (!pDialog->container.bUseReflect)
784 gtk_widget_queue_draw_area (pDialog->container.pWidget,
785 pDialog->iLeftMargin,
786 (pDialog->container.bDirectionUp ?
787 pDialog->iTopMargin :
788 pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight)),
789 pDialog->iIconSize,
790 pDialog->iIconSize);
791 else
792 gtk_widget_queue_draw (pDialog->container.pWidget);
793 }
794
_redraw_text_surface(CairoDialog * pDialog)795 static void _redraw_text_surface (CairoDialog *pDialog)
796 {
797 if (!pDialog->container.bUseReflect)
798 gtk_widget_queue_draw_area (pDialog->container.pWidget,
799 pDialog->iLeftMargin + pDialog->iIconSize + CAIRO_DIALOG_TEXT_MARGIN,
800 (pDialog->container.bDirectionUp ?
801 pDialog->iTopMargin :
802 pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight)),
803 pDialog->iTextWidth,
804 pDialog->iTextHeight);
805 else
806 gtk_widget_queue_draw (pDialog->container.pWidget);
807 }
808
gldi_dialog_redraw_interactive_widget(CairoDialog * pDialog)809 void gldi_dialog_redraw_interactive_widget (CairoDialog *pDialog)
810 {
811 if (!pDialog->container.bUseReflect)
812 gtk_widget_queue_draw_area (pDialog->container.pWidget,
813 pDialog->iLeftMargin,
814 (pDialog->container.bDirectionUp ?
815 pDialog->iTopMargin + pDialog->iMessageHeight :
816 pDialog->container.iHeight - (pDialog->iTopMargin + pDialog->iBubbleHeight) + pDialog->iMessageHeight),
817 pDialog->iInteractiveWidth,
818 pDialog->iInteractiveHeight);
819 else
820 gtk_widget_queue_draw (pDialog->container.pWidget);
821 }
822
823
_set_icon_surface(CairoDialog * pDialog,cairo_surface_t * pNewIconSurface,int iNewIconSize)824 static void _set_icon_surface (CairoDialog *pDialog, cairo_surface_t *pNewIconSurface, int iNewIconSize)
825 {
826 int iPrevMessageWidth = pDialog->iMessageWidth;
827 int iPrevMessageHeight = pDialog->iMessageHeight;
828
829 cairo_surface_destroy (pDialog->pIconBuffer);
830 if (pDialog->iIconTexture != 0)
831 _cairo_dock_delete_texture (pDialog->iIconTexture);
832
833 pDialog->pIconBuffer = pNewIconSurface;
834 if (! pNewIconSurface)
835 iNewIconSize = 0;
836
837 if (pDialog->iIconSize != iNewIconSize) // can happen if the dialog didn't have an icon before, or if the new one is NULL
838 {
839 pDialog->iIconSize = iNewIconSize;
840 _compute_dialog_sizes (pDialog);
841 }
842
843 // redraw
844 if (pDialog->iMessageWidth != iPrevMessageWidth || pDialog->iMessageHeight != iPrevMessageHeight)
845 {
846 g_object_set (pDialog->pMessageWidget, "width-request", pDialog->iMessageWidth, "height-request", pDialog->iMessageHeight, NULL); // inutile de replacer le dialogue puisque sa gravite fera le boulot.
847
848 gtk_widget_queue_draw (pDialog->container.pWidget);
849 }
850 else
851 {
852 _redraw_icon_surface (pDialog);
853 }
854 }
855
gldi_dialog_set_icon_surface(CairoDialog * pDialog,cairo_surface_t * pNewIconSurface,int iNewIconSize)856 void gldi_dialog_set_icon_surface (CairoDialog *pDialog, cairo_surface_t *pNewIconSurface, int iNewIconSize)
857 {
858 int iIconSize = (pDialog->iIconSize != 0 ? pDialog->iIconSize : myDialogsParam.iDialogIconSize);
859 cairo_surface_t *pIconBuffer = cairo_dock_duplicate_surface (pNewIconSurface, iNewIconSize, iNewIconSize, iIconSize, iIconSize);
860 _set_icon_surface (pDialog, pIconBuffer, iIconSize);
861 }
862
gldi_dialog_set_icon(CairoDialog * pDialog,const gchar * cImageFilePath)863 void gldi_dialog_set_icon (CairoDialog *pDialog, const gchar *cImageFilePath)
864 {
865 int iIconSize = (pDialog->iIconSize != 0 ? pDialog->iIconSize : myDialogsParam.iDialogIconSize);
866 cairo_surface_t *pIconBuffer = cairo_dock_create_surface_for_square_icon (cImageFilePath, iIconSize);
867
868 _set_icon_surface (pDialog, pIconBuffer, iIconSize);
869 }
870
871
_set_text_surface(CairoDialog * pDialog,cairo_surface_t * pNewTextSurface,int iNewTextWidth,int iNewTextHeight)872 static void _set_text_surface (CairoDialog *pDialog, cairo_surface_t *pNewTextSurface, int iNewTextWidth, int iNewTextHeight)
873 {
874 int iPrevMessageWidth = pDialog->iMessageWidth;
875 int iPrevMessageHeight = pDialog->iMessageHeight;
876
877 cairo_surface_destroy (pDialog->pTextBuffer);
878 pDialog->pTextBuffer = pNewTextSurface;
879 if (pDialog->iTextTexture != 0)
880 _cairo_dock_delete_texture (pDialog->iTextTexture);
881 ///pDialog->iTextTexture = cairo_dock_create_texture_from_surface (pNewTextSurface);
882
883 pDialog->iTextWidth = iNewTextWidth;
884 pDialog->iTextHeight = iNewTextHeight;
885 _compute_dialog_sizes (pDialog);
886
887 if (pDialog->iMessageWidth != iPrevMessageWidth || pDialog->iMessageHeight != iPrevMessageHeight)
888 {
889 g_object_set (pDialog->pMessageWidget, "width-request", pDialog->iMessageWidth, "height-request", pDialog->iMessageHeight, NULL); // inutile de replacer le dialogue puisque sa gravite fera le boulot.
890
891 gtk_widget_queue_draw (pDialog->container.pWidget);
892
893 gboolean bInside = pDialog->container.bInside;
894 pDialog->container.bInside = FALSE; // unfortunately the gravity is really badly handled by many WMs, so we have to replace he dialog ourselves :-/
895 gldi_dialogs_replace_all ();
896 pDialog->container.bInside = bInside;
897 }
898 else
899 {
900 _redraw_text_surface (pDialog);
901 }
902 }
903
gldi_dialog_set_message(CairoDialog * pDialog,const gchar * cMessage)904 void gldi_dialog_set_message (CairoDialog *pDialog, const gchar *cMessage)
905 {
906 cd_debug ("%s", cMessage);
907 int iNewTextWidth=0, iNewTextHeight=0;
908 cairo_surface_t *pNewTextSurface = _cairo_dock_create_dialog_text_surface (cMessage, pDialog->bUseMarkup, &iNewTextWidth, &iNewTextHeight);
909
910 _set_text_surface (pDialog, pNewTextSurface, iNewTextWidth, iNewTextHeight);
911
912 g_free (pDialog->cText);
913 pDialog->cText = g_strdup (cMessage);
914 }
gldi_dialog_set_message_printf(CairoDialog * pDialog,const gchar * cMessageFormat,...)915 void gldi_dialog_set_message_printf (CairoDialog *pDialog, const gchar *cMessageFormat, ...)
916 {
917 g_return_if_fail (cMessageFormat != NULL);
918 va_list args;
919 va_start (args, cMessageFormat);
920 gchar *cMessage = g_strdup_vprintf (cMessageFormat, args);
921 gldi_dialog_set_message (pDialog, cMessage);
922 g_free (cMessage);
923 va_end (args);
924 }
925
gldi_dialog_reload(CairoDialog * pDialog)926 void gldi_dialog_reload (CairoDialog *pDialog)
927 {
928 // re-set the GTK style class (global style may have changed between system / custom)
929 GtkStyleContext *ctx = gtk_widget_get_style_context (pDialog->pWidgetLayout);
930
931 gtk_style_context_remove_class (ctx, GTK_STYLE_CLASS_MENUITEM);
932 gtk_style_context_remove_class (ctx, "gldimenuitem");
933
934 gtk_style_context_add_class (ctx, myDialogsParam.bUseDefaultColors && myStyleParam.bUseSystemColors ? GTK_STYLE_CLASS_MENUITEM : "gldimenuitem");
935
936 // reload the text buffer (color or font may have changed)
937 if (pDialog->cText != NULL)
938 {
939 gchar *cText = pDialog->cText;
940 pDialog->cText = NULL;
941 gldi_dialog_set_message (pDialog, cText);
942 g_free (cText);
943 }
944
945 // reload sizes (radius or linewidth may have changed)
946 _compute_dialog_sizes (pDialog);
947 }
948