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 #ifndef __CAIRO_DOCK_CONTAINER__
21 #define  __CAIRO_DOCK_CONTAINER__
22 
23 #include "gldi-config.h"
24 #include <glib.h>
25 #ifdef HAVE_GLX
26 #include <GL/glx.h>  // GLXContext
27 #endif
28 #ifdef HAVE_EGL
29 #include <EGL/egl.h>  // EGLContext, EGLSurface
30 #endif
31 #include "cairo-dock-struct.h"
32 #include "cairo-dock-manager.h"
33 
34 G_BEGIN_DECLS
35 
36 /**
37 *@file cairo-dock-container.h This class defines the Containers, that are classic or hardware accelerated animated windows, and exposes common functions, such as redrawing a part of a container or popping a menu on a container.
38 *
39 * A Container is a rectangular on-screen located surface, has the notion of orientation, can hold external datas, monitors the mouse position, and has its own animation loop.
40 *
41 * Docks, Desklets, Dialogs, and Flying-containers all derive from Containers.
42 *
43 */
44 
45 // manager
46 typedef struct _GldiContainersParam GldiContainersParam;
47 typedef struct _GldiContainerAttr GldiContainerAttr;
48 
49 #ifndef _MANAGER_DEF_
50 extern GldiContainersParam myContainersParam;
51 extern GldiManager myContainersMgr;
52 extern GldiObjectManager myContainerObjectMgr;
53 #endif
54 
55 #define CD_DOUBLE_CLICK_DELAY 250  // ms
56 
57 // params
58 struct _GldiContainersParam{
59 	//gboolean bUseFakeTransparency;
60 	gint iGLAnimationDeltaT;
61 	gint iCairoAnimationDeltaT;
62 	};
63 
64 struct _GldiContainerAttr {
65 	gboolean bNoOpengl;
66 };
67 
68 /// signals
69 typedef enum {
70 	/// notification called when the menu is being built on a container. data : {Icon, GldiContainer, GtkMenu, gboolean*}
71 	NOTIFICATION_BUILD_CONTAINER_MENU = NB_NOTIFICATIONS_OBJECT,
72 	/// notification called when the menu is being built on an icon (possibly NULL). data : {Icon, GldiContainer, GtkMenu}
73 	NOTIFICATION_BUILD_ICON_MENU,
74 	/// notification called when use clicks on an icon data : {Icon, CairoDock, int}
75 	NOTIFICATION_CLICK_ICON,
76 	/// notification called when the user double-clicks on an icon. data : {Icon, CairoDock}
77 	NOTIFICATION_DOUBLE_CLICK_ICON,
78 	/// notification called when the user middle-clicks on an icon. data : {Icon, CairoDock}
79 	NOTIFICATION_MIDDLE_CLICK_ICON,
80 	/// notification called when the user scrolls on an icon. data : {Icon, CairoDock, int}
81 	NOTIFICATION_SCROLL_ICON,
82 	/// notification called when the mouse enters an icon. data : {Icon, CairoDock, gboolean*}
83 	NOTIFICATION_ENTER_ICON,
84 	/// notification called when the mouse enters a dock while dragging an object.
85 	NOTIFICATION_START_DRAG_DATA,
86 	/// notification called when something is dropped inside a container. data : {gchar*, Icon, double*, CairoDock}
87 	NOTIFICATION_DROP_DATA,
88 	/// notification called when the mouse has moved inside a container.
89 	NOTIFICATION_MOUSE_MOVED,
90 	/// notification called when a key is pressed in a container that has the focus.
91 	NOTIFICATION_KEY_PRESSED,
92 	/// notification called for the fast rendering loop on a container.
93 	NOTIFICATION_UPDATE,
94 	/// notification called for the slow rendering loop on a container.
95 	NOTIFICATION_UPDATE_SLOW,
96 	/// notification called when a container is rendered.
97 	NOTIFICATION_RENDER,
98 	NB_NOTIFICATIONS_CONTAINER
99 	} GldiContainerNotifications;
100 
101 
102 // factory
103 /// Main orientation of a container.
104 typedef enum {
105 	CAIRO_DOCK_VERTICAL = 0,
106 	CAIRO_DOCK_HORIZONTAL
107 	} CairoDockTypeHorizontality;
108 
109 struct _GldiContainerInterface {
110 	gboolean (*animation_loop) (GldiContainer *pContainer);
111 	void (*setup_menu) (GldiContainer *pContainer, Icon *pIcon, GtkWidget *pMenu);
112 	void (*detach_icon) (GldiContainer *pContainer, Icon *pIcon);
113 	void (*insert_icon) (GldiContainer *pContainer, Icon *pIcon, gboolean bAnimateIcon);
114 	};
115 
116 /// Definition of a Container, whom derive Dock, Desklet, Dialog and FlyingContainer.
117 struct _GldiContainer {
118 	/// object.
119 	GldiObject object;
120 	/// External data.
121 	gpointer pDataSlot[CAIRO_DOCK_NB_DATA_SLOT];
122 	/// window of the container.
123 	GtkWidget *pWidget;
124 	/// size of the container.
125 	gint iWidth, iHeight;
126 	/// position of the container.
127 	gint iWindowPositionX, iWindowPositionY;
128 	/// TURE is the mouse is inside the container (including the possible sub-widgets).
129 	gboolean bInside;
130 	/// TRUE if the container is horizontal, FALSE if vertical
131 	CairoDockTypeHorizontality bIsHorizontal;
132 	/// TRUE if the container is oriented upwards, FALSE if downwards.
133 	gboolean bDirectionUp;
134 	/// Source ID of the animation loop.
135 	guint iSidGLAnimation;
136 	/// interval of time between 2 animation steps.
137 	gint iAnimationDeltaT;
138 	/// X position of the mouse in the container's system of reference.
139 	gint iMouseX;
140 	/// Y position of the mouse in the container's system of reference.
141 	gint iMouseY;
142 	/// zoom applied to the container's elements.
143 	gdouble fRatio;
144 	/// TRUE if the container has a reflection power.
145 	gboolean bUseReflect;
146 	#ifdef HAVE_GLX
147 	/// OpenGL context.
148 	GLXContext glContext;
149 	void *unused;  // keep ABI compatibility
150 	#elif defined(HAVE_EGL)
151 	/// OpenGL context.
152 	EGLContext glContext;
153 	/// EGL surface.
154 	EGLSurface eglSurface;
155 	#endif
156 	/// whether the GL context is an ortho or a perspective view.
157 	gboolean bPerspectiveView;
158 	/// TRUE if a slow animation is running.
159 	gboolean bKeepSlowAnimation;
160 	/// counter for the animation loop.
161 	gint iAnimationStep;
162 	GldiContainerInterface iface;
163 
164 	gboolean bIgnoreNextReleaseEvent;
165 	gpointer reserved[4];
166 };
167 
168 
169 /// Definition of the Container backend. It defines some operations that should be, but are not, provided by GTK.
170 struct _GldiContainerManagerBackend {
171 	void (*reserve_space) (GldiContainer *pContainer, int left, int right, int top, int bottom, int left_start_y, int left_end_y, int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x);
172 	int (*get_current_desktop_index) (GldiContainer *pContainer);
173 	void (*move) (GldiContainer *pContainer, int iNumDesktop, int iAbsolutePositionX, int iAbsolutePositionY);
174 	gboolean (*is_active) (GldiContainer *pContainer);
175 	void (*present) (GldiContainer *pContainer);
176 };
177 
178 
179 /// Get the Container part of a pointer.
180 #define CAIRO_CONTAINER(p) ((GldiContainer *) (p))
181 
182 /** Say if an object is a Container.
183 *@param obj the object.
184 *@return TRUE if the object is a Container.
185 */
186 #define CAIRO_DOCK_IS_CONTAINER(obj) gldi_object_is_manager_child (GLDI_OBJECT(obj), &myContainerObjectMgr)
187 
188   /////////////
189  // WINDOW //
190 ///////////
191 
192 
193 void cairo_dock_set_containers_non_sticky (void);
194 
195 void cairo_dock_disable_containers_opacity (void);
196 
197 #define gldi_container_get_gdk_window(pContainer) gtk_widget_get_window ((pContainer)->pWidget)
198 
199 #define gldi_container_get_Xid(pContainer) GDK_WINDOW_XID (gldi_container_get_gdk_window(pContainer))
200 
201 #define gldi_container_is_visible(pContainer) gtk_widget_get_visible ((pContainer)->pWidget)
202 
203 #define gldi_display_get_pointer(xptr, yptr) do {\
204 	GdkDeviceManager *_dm = gdk_display_get_device_manager (gdk_display_get_default());\
205 	GdkDevice *_dev = gdk_device_manager_get_client_pointer (_dm);\
206 	gdk_device_get_position (_dev, NULL, xptr, yptr); } while (0)
207 
208 #define gldi_container_update_mouse_position(pContainer) do {\
209 	GdkDeviceManager *pManager = gdk_display_get_device_manager (gtk_widget_get_display (pContainer->pWidget)); \
210 	GdkDevice *pDevice = gdk_device_manager_get_client_pointer (pManager); \
211 	if ((pContainer)->bIsHorizontal) \
212 		gdk_window_get_device_position (gldi_container_get_gdk_window (pContainer), pDevice, &pContainer->iMouseX, &pContainer->iMouseY, NULL); \
213 	else \
214 		gdk_window_get_device_position (gldi_container_get_gdk_window (pContainer), pDevice, &pContainer->iMouseY, &pContainer->iMouseX, NULL); } while (0)
215 
216 
217 /** Reserve a space on the screen for a Container; other windows won't overlap this space when maximised.
218 *@param pContainer the container
219 *@param left
220 *@param right
221 *@param top
222 *@param bottom
223 *@param left_start_y
224 *@param left_end_y
225 *@param right_start_y
226 *@param right_end_y
227 *@param top_start_x
228 *@param top_end_x
229 *@param bottom_start_x
230 *@param bottom_end_x
231 */
232 void gldi_container_reserve_space (GldiContainer *pContainer, int left, int right, int top, int bottom, int left_start_y, int left_end_y, int right_start_y, int right_end_y, int top_start_x, int top_end_x, int bottom_start_x, int bottom_end_x);
233 
234 /** Get the desktop and viewports a Container is placed on.
235 *@param pContainer the container
236 *@return an index representing the desktop and viewports.
237 */
238 int gldi_container_get_current_desktop_index (GldiContainer *pContainer);
239 
240 /** Move a Container to a given desktop, viewport, and position (similar to gtk_window_move except that the position is defined on the whole desktop (made of all viewports); it's only useful if the Container is sticky).
241 *@param pContainer the container
242 *@param iNumDesktop desktop number
243 *@param iAbsolutePositionX horizontal position on the virtual screen
244 *@param iAbsolutePositionY vertical position on the virtual screen
245 */
246 void gldi_container_move (GldiContainer *pContainer, int iNumDesktop, int iAbsolutePositionX, int iAbsolutePositionY);
247 
248 /** Tell if a Container is the current active window (similar to gtk_window_is_active but actually works).
249 *@param pContainer the container
250 *@return TRUE if the Container is the current active window.
251 */
252 gboolean gldi_container_is_active (GldiContainer *pContainer);
253 
254 /** Show a Container and make it take the focus  (similar to gtk_window_present, but bypasses the WM focus steal prevention).
255 *@param pContainer the container
256 */
257 void gldi_container_present (GldiContainer *pContainer);
258 
259 
260 void gldi_container_manager_register_backend (GldiContainerManagerBackend *pBackend);
261 
262 
263 
264   ////////////
265  // REDRAW //
266 ////////////
267 
268 void cairo_dock_set_default_rgba_visual (GtkWidget *pWidget);
269 
270 /** Clear and trigger the redraw of a Container.
271 *@param pContainer the Container to redraw.
272 */
273 void cairo_dock_redraw_container (GldiContainer *pContainer);
274 
275 /** Clear and trigger the redraw of a part of a container.
276 *@param pContainer the Container to redraw.
277 *@param pArea the zone to redraw.
278 */
279 void cairo_dock_redraw_container_area (GldiContainer *pContainer, GdkRectangle *pArea);
280 
281 /** Clear and trigger the redraw of an Icon. The drawing is not done immediately, but when the expose event is received.
282 *@param icon l'icone a retracer.
283 */
284 void cairo_dock_redraw_icon (Icon *icon);
285 
286 
287 void cairo_dock_allow_widget_to_receive_data (GtkWidget *pWidget, GCallback pCallBack, gpointer data);
288 
289 /** Enable a Container to accept drag-and-drops.
290 * @param pContainer a container.
291 * @param pCallBack the function that will be called when some data is received.
292 * @param data data passed to the callback.
293 */
294 #define gldi_container_enable_drop(pContainer, pCallBack, data) cairo_dock_allow_widget_to_receive_data (pContainer->pWidget, pCallBack, data)
295 
296 void gldi_container_disable_drop (GldiContainer *pContainer);
297 
298 /** Notify everybody that a drop has just occured.
299 * @param cReceivedData the dropped data.
300 * @param pPointedIcon the icon which was pointed when the drop occured.
301 * @param fOrder the order of the icon if the drop occured on it, or LAST_ORDER if the drop occured between 2 icons.
302 * @param pContainer the container of the icon
303 */
304 void gldi_container_notify_drop_data (GldiContainer *pContainer, gchar *cReceivedData, Icon *pPointedIcon, double fOrder);
305 
306 
307 gboolean cairo_dock_emit_signal_on_container (GldiContainer *pContainer, const gchar *cSignal);
308 gboolean cairo_dock_emit_leave_signal (GldiContainer *pContainer);
309 gboolean cairo_dock_emit_enter_signal (GldiContainer *pContainer);
310 
311 /** Build the main menu of a Container.
312 *@param icon the icon that was left-clicked, or NULL if none.
313 *@param pContainer the container that was left-clicked.
314 *@return the menu.
315 */
316 GtkWidget *gldi_container_build_menu (GldiContainer *pContainer, Icon *icon);
317 
318 
319   /////////////////
320  // INPUT SHAPE //
321 /////////////////
322 
323 cairo_region_t *gldi_container_create_input_shape (GldiContainer *pContainer, int x, int y, int w, int h);
324 
325 // Note: if gdkwindow->shape == NULL, setting a NULL shape will do nothing
326 #define gldi_container_set_input_shape(pContainer, pShape) \
327 gtk_widget_input_shape_combine_region ((pContainer)->pWidget, pShape)
328 
329 
330 void gldi_register_containers_manager (void);
331 
332 G_END_DECLS
333 #endif
334