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 <string.h>
21 #include <glib/gstdio.h>
22 #include <math.h>
23
24 #include "applet-struct.h"
25 #include "applet-load-icons.h"
26 #include "applet-desktops.h"
27 #include "applet-draw.h"
28
29 typedef struct {
30 gint iNumDesktop;
31 gint iNumViewportX;
32 gint iNumViewportY;
33 gint iOneViewportWidth;
34 gint iOneViewportHeight;
35 cairo_t *pCairoContext;
36 } CDSwitcherDesktop;
37
_cd_switcher_draw_windows_on_viewport(Icon * pIcon,CDSwitcherDesktop * data)38 static void _cd_switcher_draw_windows_on_viewport (Icon *pIcon, CDSwitcherDesktop *data)
39 {
40 if (pIcon == NULL || pIcon->fInsertRemoveFactor > 0)
41 return ;
42 GldiWindowActor *actor = pIcon->pAppli;
43 if (actor->bIsHidden && ! myConfig.bDisplayHiddenWindows)
44 return ;
45 int iNumDesktop = data->iNumDesktop;
46 int iNumViewportX = data->iNumViewportX;
47 int iNumViewportY = data->iNumViewportY;
48 int iOneViewportWidth = data->iOneViewportWidth;
49 int iOneViewportHeight = data->iOneViewportHeight;
50 cairo_t *pCairoContext = data->pCairoContext;
51
52 // On calcule les coordonnees en repere absolu.
53 int x = actor->windowGeometry.x; // par rapport au viewport courant.
54 x += myData.switcher.iCurrentViewportX * g_desktopGeometry.Xscreen.width; // repere absolu
55 if (x < 0)
56 x += g_desktopGeometry.iNbViewportX * g_desktopGeometry.Xscreen.width;
57 int y = actor->windowGeometry.y;
58 y += myData.switcher.iCurrentViewportY * g_desktopGeometry.Xscreen.height;
59 if (y < 0)
60 y += g_desktopGeometry.iNbViewportY * g_desktopGeometry.Xscreen.height;
61 int w = actor->windowGeometry.width, h = actor->windowGeometry.height;
62
63 // test d'intersection avec le viewport donne.
64 //g_print (" %s : (%d;%d) %dx%d\n", pIcon->cName, x, y, w, h);
65 if ((actor->iNumDesktop != -1 && actor->iNumDesktop != iNumDesktop) ||
66 x + w <= iNumViewportX * g_desktopGeometry.Xscreen.width ||
67 x >= (iNumViewportX + 1) * g_desktopGeometry.Xscreen.width ||
68 y + h <= iNumViewportY * g_desktopGeometry.Xscreen.height ||
69 y >= (iNumViewportY + 1) * g_desktopGeometry.Xscreen.height)
70 return ;
71
72 // on dessine ses traits.
73 cairo_save (pCairoContext);
74
75 GldiWindowActor *pActiveWindow = gldi_windows_get_active ();
76
77 if (myConfig.bFillAllWindows && actor != pActiveWindow)
78 cairo_set_source_rgba (pCairoContext, myConfig.RGBWFillColors[0], myConfig.RGBWFillColors[1], myConfig.RGBWFillColors[2], myConfig.RGBWFillColors[3]);
79 else
80 {
81 if (myConfig.bUseDefaultColors)
82 gldi_style_colors_set_line_color (myDrawContext);
83 else
84 cairo_set_source_rgba (pCairoContext, myConfig.RGBWLineColors[0], myConfig.RGBWLineColors[1], myConfig.RGBWLineColors[2], myConfig.RGBWLineColors[3]);
85 }
86 cairo_rectangle (pCairoContext,
87 (1.*x/g_desktopGeometry.Xscreen.width - iNumViewportX)*iOneViewportWidth,
88 (1.*y/g_desktopGeometry.Xscreen.height - iNumViewportY)*iOneViewportHeight,
89 1.*w/g_desktopGeometry.Xscreen.width*iOneViewportWidth,
90 1.*h/g_desktopGeometry.Xscreen.height*iOneViewportHeight);
91
92 if (myConfig.bFillAllWindows || actor == pActiveWindow)
93 {
94 //g_print (" %s est la fenetre active\n", pIcon->cName);
95 cairo_fill (pCairoContext);
96 }
97 else
98 {
99 cairo_stroke (pCairoContext);
100 }
101
102 if (myConfig.bDrawIcons)
103 {
104 const CairoDockImageBuffer *pImage = gldi_appli_icon_get_image_buffer (pIcon);
105 if (pImage && pImage->pSurface)
106 {
107 double fZoomX = (double) w/g_desktopGeometry.Xscreen.width*iOneViewportWidth / pImage->iWidth;
108 double fZoomY = (double) h/g_desktopGeometry.Xscreen.height*iOneViewportHeight / pImage->iHeight;
109 double fZoom = MIN (fZoomX, fZoomY); // on garde le ratio.
110
111 cairo_translate (pCairoContext,
112 (1.*x/g_desktopGeometry.Xscreen.width - iNumViewportX)*iOneViewportWidth + (fZoomX - fZoom) * pImage->iWidth/2,
113 (1.*y/g_desktopGeometry.Xscreen.height - iNumViewportY)*iOneViewportHeight + (fZoomY - fZoom) * pImage->iHeight/2);
114 cairo_scale (pCairoContext,
115 fZoom,
116 fZoom);
117 cairo_set_source_surface (pCairoContext,
118 pImage->pSurface,
119 0.,
120 0.);
121 cairo_paint (pCairoContext);
122 }
123 }
124
125 cairo_restore (pCairoContext);
126 }
127
128
_compare_icons_stack_order(Icon * icon1,Icon * icon2)129 static int _compare_icons_stack_order (Icon *icon1, Icon *icon2)
130 {
131 if (icon1 == NULL) // les icones nulles vont a la fin.
132 return 1;
133 if (icon2 == NULL)
134 return -1;
135 if (icon1->pAppli->iStackOrder < icon2->pAppli->iStackOrder) // ordre petit => dessus => dessinee en dernier.
136 return -1;
137 else
138 return 1;
139 }
cd_switcher_draw_main_icon_compact_mode(void)140 void cd_switcher_draw_main_icon_compact_mode (void)
141 {
142 if (myData.switcher.iNbColumns == 0 || myData.switcher.iNbLines == 0) // may happen in desklet mode with a cube desktop, when the desklet is still 0x0.
143 return;
144 CD_APPLET_START_DRAWING_MY_ICON_OR_RETURN_CAIRO ();
145 ///g_return_if_fail (myDrawContext != NULL);
146 //g_print ("%s (%d;%d)\n", __func__, myData.switcher.iCurrentLine, myData.switcher.iCurrentColumn);
147 // On efface l'icone.
148 ///cairo_dock_erase_cairo_context (myDrawContext);
149
150 // definition des parametres de dessin.
151 int iWidth, iHeight;
152 CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
153
154 myData.switcher.fOneViewportHeight = (double) (iHeight - 2 * myConfig.iLineSize - (myData.switcher.iNbLines - 1) * myConfig.iInLineSize) / myData.switcher.iNbLines; //hauteur d'un bureau/viewport sans compter les lignes exterieures et interieures.
155 myData.switcher.fOneViewportWidth = (double) (iWidth - 2 * myConfig.iLineSize - (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize) / myData.switcher.iNbColumns; //largeur d'un bureau/viewport sans compter les lignes exterieures et interieures.
156 double dx=0, dy=0;
157 double w = iWidth, h = iHeight;
158 if (myConfig.bPreserveScreenRatio)
159 {
160 double r = (double) g_desktopGeometry.Xscreen.width / g_desktopGeometry.Xscreen.height;
161 double r_ = myData.switcher.fOneViewportWidth / myData.switcher.fOneViewportHeight;
162 if (r_ > r) // on etire trop en largeur.
163 {
164 myData.switcher.fOneViewportWidth /= r_ / r;
165 w = myData.switcher.fOneViewportWidth * myData.switcher.iNbColumns + 2 * myConfig.iLineSize + (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize;
166 dx = (double) (iWidth - w) / 2;
167 }
168 else
169 {
170 myData.switcher.fOneViewportHeight /= r / r_;
171 h = myData.switcher.fOneViewportHeight * myData.switcher.iNbLines + 2 * myConfig.iLineSize + (myData.switcher.iNbLines - 1) * myConfig.iInLineSize;
172 dy = (iHeight - h) / 2;
173 }
174 }
175 myData.switcher.fOffsetX = dx;
176 myData.switcher.fOffsetY = dy;
177
178 cairo_save (myDrawContext);
179 cairo_translate (myDrawContext, dx, dy);
180
181 cairo_surface_t *pSurface = NULL;
182 double fZoomX, fZoomY;
183 if (myConfig.iIconDrawing == SWICTHER_MAP_WALLPAPER)
184 {
185 pSurface = myData.pDesktopBgMapSurface;
186 }
187 if (pSurface == NULL)
188 {
189 pSurface = myData.pDefaultMapSurface;
190 }
191 fZoomX = (double) myData.switcher.fOneViewportWidth / myData.iSurfaceWidth; // both surfaces are loaded at the same size.
192 fZoomY= (double) myData.switcher.fOneViewportHeight / myData.iSurfaceHeight;
193
194 // cadre exterieur.
195 cairo_set_line_width (myDrawContext,myConfig.iLineSize);
196 if (myConfig.bUseDefaultColors)
197 gldi_style_colors_set_line_color (myDrawContext);
198 else
199 cairo_set_source_rgba(myDrawContext,myConfig.RGBLineColors[0],myConfig.RGBLineColors[1],myConfig.RGBLineColors[2],myConfig.RGBLineColors[3]);
200 cairo_rectangle(myDrawContext,
201 .5*myConfig.iLineSize,
202 .5*myConfig.iLineSize,
203 w - myConfig.iLineSize,
204 h - myConfig.iLineSize);
205
206 cairo_stroke (myDrawContext);
207
208 // lignes interieures.
209 cairo_set_line_width (myDrawContext,myConfig.iInLineSize);
210 if (myConfig.bUseDefaultColors)
211 gldi_style_colors_set_line_color (myDrawContext);
212 else
213 cairo_set_source_rgba (myDrawContext,myConfig.RGBInLineColors[0],myConfig.RGBInLineColors[1],myConfig.RGBInLineColors[2],myConfig.RGBInLineColors[3]);
214 double xi, yj;
215 int i, j;
216 for (i = 1; i < myData.switcher.iNbColumns; i ++) // lignes verticales.
217 {
218 xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
219 cairo_move_to (myDrawContext, xi, myConfig.iLineSize);
220 cairo_rel_line_to (myDrawContext, 0, h - 2*myConfig.iLineSize);
221 cairo_stroke (myDrawContext);
222 }
223 for (j = 1; j < myData.switcher.iNbLines; j ++) // lignes horizontales.
224 {
225 yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
226 cairo_move_to (myDrawContext, myConfig.iLineSize, yj);
227 cairo_rel_line_to (myDrawContext, w - 2*myConfig.iLineSize, 0);
228 cairo_stroke (myDrawContext);
229 }
230
231 GList *pWindowList = NULL;
232 if (myConfig.bDrawWindows)
233 {
234 pWindowList = cairo_dock_get_current_applis_list ();
235 pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
236 }
237
238 // chaque bureau/viewport.
239 int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
240 int k = 0, N = g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY;
241 for (j = 0; j < myData.switcher.iNbLines && k < N; j ++)
242 {
243 for (i = 0; i < myData.switcher.iNbColumns && k < N; i ++)
244 {
245 cairo_save (myDrawContext);
246
247 xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize);
248 yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize);
249
250 cairo_translate (myDrawContext,
251 xi,
252 yj);
253
254 cairo_scale (myDrawContext,
255 fZoomX,
256 fZoomY);
257 cairo_set_source_surface (myDrawContext,
258 pSurface,
259 0.,
260 0.);
261 cairo_paint(myDrawContext);
262
263 cairo_restore (myDrawContext);
264
265 if ((myConfig.iDrawCurrentDesktopMode == SWICTHER_FILL_INVERTED && (i != myData.switcher.iCurrentColumn || j != myData.switcher.iCurrentLine))
266 || (myConfig.iDrawCurrentDesktopMode == SWICTHER_FILL && (i == myData.switcher.iCurrentColumn && j == myData.switcher.iCurrentLine)))
267 {
268 cairo_save (myDrawContext);
269
270 if (myConfig.bUseDefaultColors)
271 gldi_style_colors_set_selected_bg_color (myDrawContext);
272 else
273 cairo_set_source_rgba (myDrawContext, myConfig.RGBIndColors[0], myConfig.RGBIndColors[1], myConfig.RGBIndColors[2], myConfig.RGBIndColors[3]);
274 cairo_rectangle(myDrawContext,
275 xi - .5*myConfig.iLineSize,
276 yj - .5*myConfig.iLineSize,
277 myData.switcher.fOneViewportWidth + myConfig.iLineSize,
278 myData.switcher.fOneViewportHeight + myConfig.iLineSize);
279 cairo_fill (myDrawContext);
280
281 cairo_restore (myDrawContext);
282 }
283
284 if (myConfig.bDrawWindows)
285 {
286 cairo_save (myDrawContext);
287
288 cairo_translate (myDrawContext,
289 xi,
290 yj);
291 cairo_set_line_width (myDrawContext, 1.);
292 cairo_rectangle (myDrawContext,
293 0.,
294 0.,
295 myData.switcher.fOneViewportWidth,
296 myData.switcher.fOneViewportHeight);
297 cairo_clip (myDrawContext);
298
299 //g_print (" dessin des fenetres du bureau (%d;%d;%d) ...\n", iNumDesktop, iNumViewportX, iNumViewportY);
300 CDSwitcherDesktop data = {iNumDesktop, iNumViewportX, iNumViewportY, (int) myData.switcher.fOneViewportWidth, (int) myData.switcher.fOneViewportHeight, myDrawContext};
301 g_list_foreach (pWindowList, (GFunc) _cd_switcher_draw_windows_on_viewport, &data);
302
303 cairo_restore (myDrawContext);
304 }
305
306 iNumViewportX ++;
307 if (iNumViewportX == g_desktopGeometry.iNbViewportX)
308 {
309 iNumViewportX = 0;
310 iNumViewportY ++;
311 if (iNumViewportY == g_desktopGeometry.iNbViewportY)
312 {
313 iNumViewportY = 0;
314 iNumDesktop ++;
315 }
316 }
317 k ++;
318 }
319 }
320
321 // dessin de l'indicateur sur le bureau courant (on le fait maintenant car dans le cas ou la ligne interieure est plus petite que la ligne de l'indicateur, les surfaces suivantes recouvreraient en partie la ligne.
322 if (myConfig.iDrawCurrentDesktopMode == SWICTHER_DRAW_FRAME)
323 {
324 i = myData.switcher.iCurrentColumn;
325 j = myData.switcher.iCurrentLine;
326 xi = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize);
327 yj = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize);
328
329 cairo_set_line_width (myDrawContext,myConfig.iLineSize);
330 if (myConfig.bUseDefaultColors)
331 gldi_style_colors_set_selected_bg_color (myDrawContext);
332 else
333 cairo_set_source_rgba (myDrawContext,myConfig.RGBIndColors[0],myConfig.RGBIndColors[1],myConfig.RGBIndColors[2],myConfig.RGBIndColors[3]);
334 cairo_rectangle(myDrawContext,
335 xi - .5*myConfig.iLineSize,
336 yj - .5*myConfig.iLineSize,
337 myData.switcher.fOneViewportWidth + myConfig.iLineSize,
338 myData.switcher.fOneViewportHeight + myConfig.iLineSize);
339
340 if (myConfig.iDrawCurrentDesktopMode == SWICTHER_FILL)
341 cairo_fill (myDrawContext); // maybe we need to fill it with an alpha pattern in case we use the global style color ?...
342 else
343 {
344 cairo_set_line_width (myDrawContext, MIN (4, 2*myConfig.iLineSize));
345 cairo_stroke(myDrawContext);
346 }
347 }
348
349 cairo_restore (myDrawContext);
350 g_list_free (pWindowList); // le contenu appartient a la hash table, mais pas la liste.
351
352 CD_APPLET_FINISH_DRAWING_MY_ICON_CAIRO;
353 }
354
355
cd_switcher_draw_main_icon_expanded_mode(void)356 void cd_switcher_draw_main_icon_expanded_mode (void)
357 {
358 // apply the desktop bg or the user image on the main icon, in dock mode
359 int iWidth, iHeight;
360
361 if (myDock)
362 {
363 CD_APPLET_GET_MY_ICON_EXTENT (&iWidth, &iHeight);
364 myData.switcher.fOneViewportHeight = (iHeight - 2 * myConfig.iLineSize - (myData.switcher.iNbLines - 1) * myConfig.iInLineSize) / myData.switcher.iNbLines; //hauteur d'un bureau/viewport sans compter les lignes exterieures et interieures.
365 myData.switcher.fOneViewportWidth = (iWidth - 2 * myConfig.iLineSize - (myData.switcher.iNbColumns - 1) * myConfig.iInLineSize) / myData.switcher.iNbColumns; //largeur d'un bureau/viewport sans compter les lignes exterieures et interieures.
366
367 cairo_surface_t *pSurface = NULL;
368 double fZoomX, fZoomY;
369 if (myConfig.iIconDrawing == SWICTHER_MAP_WALLPAPER)
370 {
371 cairo_dock_erase_cairo_context (myDrawContext);
372
373 pSurface = myData.pDesktopBgMapSurface;
374 fZoomX = 1. * iWidth / myData.iSurfaceWidth;
375 fZoomY= 1. * iHeight / myData.iSurfaceHeight;
376 cairo_translate (myDrawContext,
377 0.,
378 0.);
379
380 cairo_save (myDrawContext);
381 cairo_scale (myDrawContext,
382 fZoomX ,
383 fZoomY );
384 cairo_set_source_surface (myDrawContext,
385 pSurface,
386 0.,
387 0.);
388 cairo_paint(myDrawContext);
389 cairo_restore (myDrawContext);
390
391 if (CD_APPLET_MY_CONTAINER_IS_OPENGL)
392 cairo_dock_update_icon_texture (myIcon);
393 }
394 else
395 {
396 CD_APPLET_SET_IMAGE_ON_MY_ICON (MY_APPLET_SHARE_DATA_DIR"/"MY_APPLET_ICON_FILE);
397 }
398 }
399
400 if (myConfig.bDrawWindows)
401 {
402 GList *pWindowList = cairo_dock_get_current_applis_list ();
403 pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
404
405 CDSwitcherDesktop data;
406 int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
407 cairo_t *pCairoContext;
408 Icon *pIcon;
409 GList *pIconsList = CD_APPLET_MY_ICONS_LIST;
410 GList *ic;
411 for (ic = pIconsList; ic != NULL; ic = ic->next)
412 {
413 pIcon = ic->data;
414 cairo_dock_get_icon_extent (pIcon, &iWidth, &iHeight);
415
416 pCairoContext = cairo_create (pIcon->image.pSurface);
417 cairo_set_line_width (pCairoContext, 1.);
418 if (myConfig.bUseDefaultColors)
419 gldi_style_colors_set_line_color (myDrawContext);
420 else
421 cairo_set_source_rgba (pCairoContext, myConfig.RGBWLineColors[0], myConfig.RGBWLineColors[1], myConfig.RGBWLineColors[2], myConfig.RGBWLineColors[3]);
422
423 data.iNumDesktop = iNumDesktop;
424 data.iNumViewportX = iNumViewportX;
425 data.iNumViewportY = iNumViewportY;
426 data.iOneViewportWidth = iWidth;
427 data.iOneViewportHeight = iHeight;
428 data.pCairoContext = pCairoContext;
429 g_list_foreach (pWindowList, (GFunc) _cd_switcher_draw_windows_on_viewport, &data);
430
431 iNumViewportX ++;
432 if (iNumViewportX == g_desktopGeometry.iNbViewportX)
433 {
434 iNumViewportY ++;
435 if (iNumViewportY == g_desktopGeometry.iNbViewportY)
436 iNumDesktop ++;
437 }
438 cairo_destroy (pCairoContext);
439 }
440 g_list_free (pWindowList); // le contenu appartient a la hash table, mais pas la liste.
441 }
442 }
443
444 /*Fonction de base pour toutes les autres*/
cd_switcher_draw_main_icon(void)445 void cd_switcher_draw_main_icon (void)
446 {
447 cd_message ("%s (%d)", __func__, myConfig.bCompactView);
448 if (myConfig.bCompactView)
449 {
450 cd_switcher_draw_main_icon_compact_mode ();
451 }
452 else
453 {
454 cd_switcher_draw_main_icon_expanded_mode ();
455 }
456
457 CD_APPLET_REDRAW_MY_ICON;
458 }
459
460
cd_switcher_draw_desktops_bounding_box(CairoDesklet * pDesklet)461 void cd_switcher_draw_desktops_bounding_box (CairoDesklet *pDesklet)
462 {
463 CD_APPLET_ENTER;
464 //g_print ("%s (%.2Fx%.2f)\n", __func__, myData.switcher.fOneViewportWidth, myData.switcher.fOneViewportHeight);
465 double x, y, w, h;
466 glTranslatef (-pDesklet->container.iWidth/2, -pDesklet->container.iHeight/2, 0.);
467
468 w = myData.switcher.fOneViewportWidth/2;
469 h = myData.switcher.fOneViewportHeight/2;
470 int i, j;
471 int k = 0, N = g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY;
472
473 for (j = 0; j < myData.switcher.iNbLines; j ++) // lignes horizontales.
474 {
475 y = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
476 y = pDesklet->container.iHeight - (y + h + myData.switcher.fOffsetY);
477
478 for (i = 0; i < myData.switcher.iNbColumns; i ++) // lignes verticales.
479 {
480 x = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
481 x += w + myData.switcher.fOffsetX;
482
483 glLoadName(i * myData.switcher.iNbLines + j + 1); // +1 pour ne pas avoir 0.
484
485 glBegin(GL_QUADS);
486 glVertex3f(x-w, y+h, 0.);
487 glVertex3f(x+w, y+h, 0.);
488 glVertex3f(x+w, y-h, 0.);
489 glVertex3f(x-w, y-h, 0.);
490 glEnd();
491
492 k ++;
493 if (k == N)
494 break;
495 }
496 }
497 CD_APPLET_LEAVE ();
498 }
499
cd_switcher_extract_viewport_coords_from_picked_object(CairoDesklet * pDesklet,int * iCoordX,int * iCoordY)500 void cd_switcher_extract_viewport_coords_from_picked_object (CairoDesklet *pDesklet, int *iCoordX, int *iCoordY)
501 {
502 //g_print ("%s (%d)\n", __func__, pDesklet->iPickedObject);
503 if (pDesklet->iPickedObject != 0)
504 {
505 pDesklet->iPickedObject --; // cf le +1
506 int i, j;
507 i = pDesklet->iPickedObject / myData.switcher.iNbLines;
508 j = pDesklet->iPickedObject % myData.switcher.iNbLines;
509 //g_print ("bureau (%d;%d)\n", i, j);
510
511 double x, y, w, h;
512 w = myData.switcher.fOneViewportWidth/2;
513 h = myData.switcher.fOneViewportHeight/2;
514 x = myConfig.iLineSize + i * (myData.switcher.fOneViewportWidth + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
515 x += w + myData.switcher.fOffsetX;
516 y = myConfig.iLineSize + j * (myData.switcher.fOneViewportHeight + myConfig.iInLineSize) - .5*myConfig.iInLineSize;
517 y += h + myData.switcher.fOffsetY;
518 *iCoordX = x;
519 *iCoordY = y;
520 }
521 }
522
523
_show_window(GtkMenuItem * menu_item,Icon * pIcon)524 static void _show_window (GtkMenuItem *menu_item, Icon *pIcon)
525 {
526 CD_APPLET_ENTER;
527 gldi_window_show (pIcon->pAppli);
528 CD_APPLET_LEAVE ();
529 }
530
_show_desktop(GtkMenuItem * menu_item,gpointer data)531 static void _show_desktop (GtkMenuItem *menu_item, gpointer data)
532 {
533 CD_APPLET_ENTER;
534 int iIndex = GPOINTER_TO_INT (data);
535 int iNumDesktop, iNumViewportX, iNumViewportY;
536 cd_switcher_compute_desktop_from_index (iIndex, &iNumDesktop, &iNumViewportX, &iNumViewportY);
537
538 if (iNumViewportX != myData.switcher.iCurrentViewportX
539 || iNumViewportY != myData.switcher.iCurrentViewportY
540 || iNumDesktop != myData.switcher.iCurrentDesktop)
541 gldi_desktop_set_current (iNumDesktop, iNumViewportX, iNumViewportY);
542 CD_APPLET_LEAVE ();
543 }
_cd_switcher_add_window_on_viewport(Icon * pIcon,int iNumDesktop,int iNumViewportX,int iNumViewportY,GtkWidget * pMenu)544 static void _cd_switcher_add_window_on_viewport (Icon *pIcon, int iNumDesktop, int iNumViewportX, int iNumViewportY, GtkWidget *pMenu)
545 {
546 //g_print (" + %s\n", pIcon->cName);
547
548 // on cree une copie de la surface de l'icone a la taille du menu.
549 GdkPixbuf *pixbuf = cairo_dock_icon_buffer_to_pixbuf (pIcon);
550 if (pixbuf == NULL) // icon not loaded (because not in a dock, because inhibited)
551 {
552 const gchar *cIcon = cairo_dock_get_class_icon (pIcon->cClass);
553 gint iDesiredIconSize = cairo_dock_search_icon_size (GTK_ICON_SIZE_LARGE_TOOLBAR); // 24px
554 gchar *cIconPath = cairo_dock_search_icon_s_path (cIcon, iDesiredIconSize);
555 if (cIconPath)
556 {
557 pixbuf = gdk_pixbuf_new_from_file_at_size (cIconPath,
558 iDesiredIconSize,
559 iDesiredIconSize,
560 NULL);
561 }
562 }
563
564 // on ajoute une entree au menu avec le pixbuf.
565 gchar *cLabel = cairo_dock_cut_string (pIcon->cName, 50);
566 GtkWidget *pMenuItem = gldi_menu_add_item (pMenu, cLabel, "", G_CALLBACK (_show_window), pIcon);
567 g_free (cLabel);
568
569 if (pixbuf)
570 {
571 GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
572 gldi_menu_item_set_image (pMenuItem, image);
573 g_object_unref (pixbuf);
574 }
575 }
cd_switcher_build_windows_list(GtkWidget * pMenu)576 void cd_switcher_build_windows_list (GtkWidget *pMenu)
577 {
578 GList *pWindowList = NULL;
579 pWindowList = cairo_dock_get_current_applis_list ();
580 pWindowList = g_list_sort (pWindowList, (GCompareFunc) _compare_icons_stack_order);
581
582 // chaque bureau/viewport.
583 int iNumDesktop=0, iNumViewportX=0, iNumViewportY=0;
584 int k = 0, N = g_desktopGeometry.iNbDesktops * g_desktopGeometry.iNbViewportX * g_desktopGeometry.iNbViewportY;
585 int iIndex = cd_switcher_compute_index_from_desktop (myData.switcher.iCurrentDesktop, myData.switcher.iCurrentViewportX, myData.switcher.iCurrentViewportY);
586 GString *sDesktopName = g_string_new ("");
587 int i, j;
588 for (j = 0; j < myData.switcher.iNbLines; j ++)
589 {
590 for (i = 0; i < myData.switcher.iNbColumns; i ++)
591 {
592 // on ajoute le nom du bureau/viewport dans le menu.
593 GtkWidget *pMenuItem = gtk_separator_menu_item_new ();
594 gtk_menu_shell_append(GTK_MENU_SHELL (pMenu), pMenuItem);
595 g_object_set (pMenuItem, "height-request", 3, NULL);
596
597 if (k < myData.iNbNames)
598 {
599 if (k == iIndex)
600 g_string_printf (sDesktopName, "<b>%s (%s)</b>", myData.cDesktopNames[k], D_("Current"));
601 else
602 g_string_printf (sDesktopName, "<b>%s</b>", myData.cDesktopNames[k]);
603 }
604 else
605 {
606 if (k == iIndex)
607 g_string_printf (sDesktopName, "<b>%s %d (%s)</b>", D_("Desktop"), k+1, D_("Current"));
608 else
609 g_string_printf (sDesktopName, "<b>%s %d</b>", D_("Desktop"), k+1);
610 }
611 pMenuItem = gldi_menu_add_item (pMenu, sDesktopName->str, NULL, G_CALLBACK (_show_desktop), GINT_TO_POINTER (k));
612 GtkWidget *pLabel = gtk_bin_get_child (GTK_BIN(pMenuItem));
613 gtk_label_set_use_markup (GTK_LABEL (pLabel), TRUE);
614 gtk_misc_set_alignment (GTK_MISC (pLabel), .5, .5);
615
616 pMenuItem = gtk_separator_menu_item_new ();
617 gtk_menu_shell_append(GTK_MENU_SHELL (pMenu), pMenuItem);
618 g_object_set (pMenuItem, "height-request", 3, NULL);
619
620 // on ajoute les fenetres du viewport au menu.
621 cd_debug ("Windows' listing (%d;%d;%d) ...", iNumDesktop, iNumViewportX, iNumViewportY);
622 cd_switcher_foreach_window_on_viewport (iNumDesktop,
623 iNumViewportX,
624 iNumViewportY,
625 (CDSwitcherActionOnViewportFunc) _cd_switcher_add_window_on_viewport,
626 pMenu);
627
628 // on passe au viewport suivant.
629 iNumViewportX ++;
630 if (iNumViewportX == g_desktopGeometry.iNbViewportX)
631 {
632 iNumViewportX = 0;
633 iNumViewportY ++;
634 if (iNumViewportY == g_desktopGeometry.iNbViewportY)
635 {
636 iNumViewportY = 0;
637 iNumDesktop ++;
638 }
639 }
640 k ++;
641 if (k == N)
642 break ;
643 }
644 }
645 g_string_free (sDesktopName, TRUE);
646 }
647
648
649
_cd_switcher_move_window_to_viewport(Icon * pIcon,int iNumDesktop,int iNumViewportX,int iNumViewportY,gint * data)650 static void _cd_switcher_move_window_to_viewport (Icon *pIcon, int iNumDesktop, int iNumViewportX, int iNumViewportY, gint *data)
651 {
652 int iDestNumDesktop = data[0];
653 int iDestNumViewportX = data[1];
654 int iDestNumViewportY = data[2];
655
656 gldi_window_move_to_desktop (pIcon->pAppli,
657 iDestNumDesktop,
658 (iDestNumViewportX - myData.switcher.iCurrentViewportX) * g_desktopGeometry.Xscreen.width,
659 (iDestNumViewportY - myData.switcher.iCurrentViewportY) * g_desktopGeometry.Xscreen.height);
660 }
cd_switcher_move_current_desktop_to(int iNumDesktop,int iNumViewportX,int iNumViewportY)661 void cd_switcher_move_current_desktop_to (int iNumDesktop, int iNumViewportX, int iNumViewportY)
662 {
663 gint data[3] = {iNumDesktop, iNumViewportX, iNumViewportY};
664 cd_switcher_foreach_window_on_viewport (myData.switcher.iCurrentDesktop,
665 myData.switcher.iCurrentViewportX,
666 myData.switcher.iCurrentViewportY,
667 (CDSwitcherActionOnViewportFunc) _cd_switcher_move_window_to_viewport,
668 data);
669 }
670