1 #ifndef MULTITAB_H
2 #define MULTITAB_H
3 /*
4     roxterm - VTE/GTK terminal emulator with tabs
5     Copyright (C) 2004-2015 Tony Houghton <h@realh.co.uk>
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (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 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 */
21 
22 /* Hierarchy of multiple windows, each containing multiple tabs */
23 
24 #include "menutree.h"
25 #include "options.h"
26 
27 typedef struct MultiTab MultiTab;
28 typedef struct MultiWin MultiWin;
29 
30 /* This type of function is called whenever a new tab/window is created; it
31  * should return a widget to be the main content of the tab/window.
32  * user_data_template is either the data belonging to the tab active when the
33  * user created a new tab, or in the case of the window created by
34  * multi_tab_init, the data passed to multi_tab_init; it's const because it's
35  * intended to be a template for creating new data, which is passed back via
36  * new_user_data; title for tab should also be passed back.
37  * Returned widget is the top-most widget to add to the GtkNotebook, while
38  * active_widget is used to return a widget to attach signal/event handlers to.
39  * If the function exits with adjustment non-NULL it is used for handling
40  * scroll menu actions.
41  */
42 typedef GtkWidget *(*MultiTabFiller) (MultiWin * win, MultiTab * tab,
43     gpointer user_data_template, gpointer * new_user_data,
44     GtkWidget ** active_widget, GtkAdjustment **adjustment);
45 
46 /* Called when a tab is destroyed, with the data passed as new_user_data above
47  */
48 typedef void (*MultiTabDestructor) (gpointer user_data);
49 
50 /* Called to connect menu action signal handlers to a window */
51 typedef void (*MultiWinMenuSignalConnector) (MultiWin * win);
52 
53 /* Called when a window wants to know what geometry hints to use for a child
54  * widget; the user_data is the data returned by MultiTabFiller's new_user_data.
55  * The geom should be filled in with the values for the active widget only;
56  * the caling code will work out what it has to add for the notebook, scrollbar
57  * and window decorations etc.
58  */
59 typedef void (*MultiWinGeometryFunc) (gpointer user_data, GdkGeometry * geom,
60     GdkWindowHints * hints);
61 
62 /* If pixels is FALSE: Return grid size in *pwidth and *pheight.
63  * If pixels is TRUE: Given a grid size in *pwidth and *pheight, update them to
64  * the total size of the widget required for it. If a size in is -1 use the
65  * widget's current grid size instead.
66  */
67 typedef void (*MultiWinSizeFunc) (gpointer user_data, gboolean pixels,
68     int *pwidth, int *pheight);
69 
70 /* Return the profile's default size in char cells */
71 typedef void (*MultiWinDefaultSizeFunc)(gpointer user_data,
72         int *width, int *height);
73 
74 /* Called when a tab is selected */
75 typedef void (*MultiTabSelectionHandler) (gpointer user_data, MultiTab * tab);
76 
77 /* Called when a tab is dragged to a new window; should be used to try to make
78  * sure page is same size as other tabs in new window and to update references.
79  * old_win is NULL if the tab's previous window was destroyed.
80  */
81 typedef void (*MultiTabToNewWindowHandler)(MultiWin *win, MultiTab *tab,
82         MultiWin *old_win);
83 
84 /* Called when the zoom factor is changed */
85 typedef void (*MultiWinZoomHandler)(gpointer user_data, double zoom_factor,
86         int zoom_index);
87 
88 /* Called to find out whether to use menu shortcuts */
89 typedef void (*MultiWinGetDisableMenuShortcuts)(gpointer user_data,
90     gboolean *general, gboolean *tabs);
91 
92 /* As tab position can be set by user we need another function to get this */
93 typedef GtkPositionType(*MultiWinGetTabPos)(gpointer user_data);
94 
95 /* Called when a window or tab is about to be closed. If it's a tab, event is
96  * NULL and data is the tab's user_data. If event is non-NULL data is a
97  * MultiWin *. event is not necessarily a valid event, don't dereference it
98  * even if non-NULL.
99  * Return FALSE to close, TRUE to keep open. */
100 typedef gboolean (*MultiWinDeleteHandler)(GtkWidget *, GdkEvent *,
101         gpointer data);
102 
103 /* Return whether to show close buttons in tabs */
104 typedef gboolean (*MultiTabGetShowCloseButton)(gpointer user_data);
105 
106 /* Needed externally */
107 extern MultiWinGetDisableMenuShortcuts multi_win_get_disable_menu_shortcuts;
108 
109 /* Whether to open a new tab adjacent to current one */
110 typedef gboolean (*MultiTabGetNewTabAdjacent)(gpointer user_data);
111 
112 /* Connects signals after a new tab has been shown */
113 typedef void (*MultiTabConnectMiscSignals)(gpointer user_data);
114 
115 /* Call to set up function hooks. See MultiTabFiller etc above.
116  * menu_signal_connector is called each time a new window is created to give
117  * the client a chance to connect its signal handlers; each handler will
118  * probably need to call multi_win_get_user_data_for_current_tab () */
119 void
120 multi_tab_init(MultiTabFiller filler, MultiTabDestructor destructor,
121     MultiWinMenuSignalConnector menu_signal_connector,
122     MultiWinGeometryFunc, MultiWinSizeFunc, MultiWinDefaultSizeFunc,
123     MultiTabToNewWindowHandler,
124     MultiWinZoomHandler, MultiWinGetDisableMenuShortcuts, MultiWinGetTabPos,
125     MultiWinDeleteHandler, MultiTabGetShowCloseButton,
126     MultiTabGetNewTabAdjacent, MultiTabConnectMiscSignals);
127 
128 /* Register a MultiTabSelectionHandler (see above) */
129 void
130 multi_tab_connect_tab_selection_handler(MultiWin *, MultiTabSelectionHandler);
131 
132 MultiTab *multi_tab_new(MultiWin * parent, gpointer user_data_template);
133 
134 /* When all tabs are destroyed the window is destroyed too */
135 void multi_tab_delete(MultiTab *);
136 
137 GtkWidget *multi_tab_get_widget(MultiTab *);
138 
139 /* Sets the title which is used to build the actual title from title_template.
140  */
141 void multi_tab_set_window_title(MultiTab *, const char *);
142 
143 /* See multi_win_set-title */
144 void multi_tab_set_window_title_template(MultiTab *, const char *);
145 
146 const char *multi_tab_get_window_title_template(MultiTab *);
147 
148 gboolean multi_tab_get_title_template_locked(MultiTab *);
149 
150 void multi_tab_set_title_template_locked(MultiTab *, gboolean);
151 
152 /* Not the full title */
153 const char *multi_tab_get_window_title(MultiTab *);
154 
155 void multi_tab_popup_menu_at_pointer(MultiTab * tab);
156 
157 gpointer multi_tab_get_user_data(MultiTab *);
158 
159 /* Returns the notebook page number */
160 int multi_tab_get_page_num(MultiTab *);
161 
162 /* Declared before other multi_win_* funcs because needed by inline function */
163 GtkNotebook *multi_win_get_notebook(MultiWin *win);
164 
165 MultiWin *multi_tab_get_parent(MultiTab *tab);
166 
multi_tab_get_notebook(MultiTab * tab)167 inline static GtkNotebook *multi_tab_get_notebook(MultiTab *tab)
168 {
169     return multi_win_get_notebook(multi_tab_get_parent(tab));
170 }
171 
172 /* Adds reference to widget but label and menutree widgets are lost;
173  * if notify_only this function assumes the tab has already been moved by
174  * GTK and it's just being called for notification.
175  * Returns TRUE if win has no tabs left and is destroyed.
176  */
177 gboolean multi_tab_remove_from_parent(MultiTab *tab, gboolean notify_only);
178 
179 /* Moves a tab to the given position in the notebook; if reorder is TRUE
180  * this function does the reordering otherwise it assumes the reordering has
181  * already been done and it just updates data structs */
182 void multi_tab_move_to_position(MultiTab *tab, int position, gboolean reorder);
183 
184 /* Move tab to a different window */
185 void multi_tab_move_to_new_window(MultiWin *win, MultiTab *tab, int position);
186 
187 /* widget is the top-level child of the notebook, as would be passed in a drag
188  * received event for a GtkNotebook dragged tab.
189  */
190 MultiTab *multi_tab_get_from_widget(GtkWidget *widget);
191 
192 /* Make the tab flash orange or something */
193 void multi_tab_draw_attention(MultiTab *tab);
194 void multi_tab_cancel_attention(MultiTab *tab);
195 
196 void multi_tab_add_close_button(MultiTab *tab);
197 void multi_tab_remove_close_button(MultiTab *tab);
198 void multi_tab_set_status_icon_name(MultiTab *tab, const char *name);
199 
200 void multi_tab_set_middle_click_tab_action(MultiTab *tab, int action);
201 
202 /* In following functions a zoom_index of -1 means default */
203 
204 typedef enum {
205     MULTI_WIN_DEFAULT_SIZE,
206     MULTI_WIN_FULL_SCREEN,
207     MULTI_WIN_MAXIMISED
208 } MultiWinSizing;
209 
210 /* If this is set all windows will be given a unique role based on it */
211 void multi_win_set_role_prefix(const char *role_prefix);
212 
213 /* Create a new window with default settings, adding it to main list */
214 MultiWin *multi_win_new_full(Options *shortcuts, int zoom_index,
215         gpointer user_data_template, const char *geom,
216         MultiWinSizing sizing, GtkPositionType tab_pos, gboolean borderless,
217         gboolean always_show_tabs, gboolean add_tab_button);
218 
multi_win_new_with_geom(Options * shortcuts,int zoom_index,gpointer user_data_template,const char * geom,GtkPositionType tab_pos,gboolean borderless,gboolean always_show_tabs,gboolean add_tab_button)219 inline static MultiWin *multi_win_new_with_geom(Options *shortcuts,
220         int zoom_index, gpointer user_data_template,
221         const char *geom, GtkPositionType tab_pos, gboolean borderless,
222         gboolean always_show_tabs, gboolean add_tab_button)
223 {
224     return multi_win_new_full(shortcuts, zoom_index,
225                   user_data_template, geom, MULTI_WIN_DEFAULT_SIZE,
226                   tab_pos, borderless, always_show_tabs, add_tab_button);
227 }
228 
multi_win_new(Options * shortcuts,int zoom_index,gpointer user_data_template,GtkPositionType tab_pos,gboolean borderless,gboolean always_show_tabs,gboolean add_tab_button)229 inline static MultiWin *multi_win_new(Options *shortcuts, int zoom_index,
230         gpointer user_data_template, GtkPositionType tab_pos, gboolean borderless,
231         gboolean always_show_tabs, gboolean add_tab_button)
232 {
233     return multi_win_new_full(shortcuts, zoom_index,
234                   user_data_template, NULL, MULTI_WIN_DEFAULT_SIZE,
235                   tab_pos, borderless, always_show_tabs, add_tab_button);
236 }
237 
238 /* Creates a new window that's the same as the old one except with a different
239  * profile etc
240  */
241 MultiWin *multi_win_clone(MultiWin *old,
242         gpointer user_data_template, gboolean always_show_tabs);
243 
multi_win_new_fullscreen(Options * shortcuts,int zoom_index,gpointer user_data_template,GtkPositionType tab_pos,gboolean borderless,gboolean always_show_tabs,gboolean add_tab_button)244 inline static MultiWin *multi_win_new_fullscreen(Options *shortcuts,
245         int zoom_index, gpointer user_data_template,
246         GtkPositionType tab_pos, gboolean borderless,
247         gboolean always_show_tabs, gboolean add_tab_button)
248 {
249     return multi_win_new_full(shortcuts, zoom_index,
250                   user_data_template, NULL, MULTI_WIN_FULL_SCREEN,
251                   tab_pos, borderless, always_show_tabs, add_tab_button);
252 }
253 
multi_win_new_maximised(Options * shortcuts,int zoom_index,gpointer user_data_template,GtkPositionType tab_pos,gboolean borderless,gboolean always_show_tabs,gboolean add_tab_button)254 inline static MultiWin *multi_win_new_maximised(Options *shortcuts,
255         int zoom_index, gpointer user_data_template,
256         GtkPositionType tab_pos, gboolean borderless,
257         gboolean always_show_tabs, gboolean add_tab_button)
258 {
259     return multi_win_new_full(shortcuts, zoom_index,
260                   user_data_template, NULL, MULTI_WIN_MAXIMISED,
261                   tab_pos, borderless, always_show_tabs, add_tab_button);
262 }
263 
264 /* Create a new window without a new child tab, ready to have an existing
265  * tab moved to it. Window isn't shown yet because we don't know how big we
266  * want it to be until it contains a tab. */
267 MultiWin *multi_win_new_blank(Options *shortcuts, int zoom_index,
268         gboolean disable_menu_shortcuts, gboolean disable_tab_shortcuts,
269         GtkPositionType tab_pos, gboolean always_show_tabs,
270         gboolean add_tab_button);
271 
272 /* Creates a new "blank" window ready for a dragged tab at given coords */
273 MultiWin *multi_win_new_for_tab(int x, int y, MultiTab *tab);
274 
275 void multi_win_show(MultiWin *win);
276 
277 /* Deletes a window, clearing up its data and removing it from main list, also
278  * destroying the GtkWindow if it hasn't been destroyed already. When all
279  * windows are destroyed it calls gtk_main_quit() */
280 void multi_win_delete(MultiWin *);
281 
282 void multi_win_set_borderless(MultiWin *win, gboolean borderless);
283 
284 void multi_win_set_fullscreen(MultiWin *win, gboolean fullscreen);
285 
286 GtkWidget *multi_win_get_widget(MultiWin * win);
287 
288 gboolean multi_win_is_fullscreen(MultiWin *win);
289 
290 gboolean multi_win_is_maximised(MultiWin *win);
291 
292 gboolean multi_win_is_borderless(MultiWin *win);
293 
294 int multi_win_get_zoom_index(MultiWin *win);
295 
296 double multi_win_get_zoom_factor(MultiWin *win);
297 
298 int multi_win_get_nearest_index_for_zoom(double factor);
299 
300 /* Adds signal handlers for "activate" to an item in both menus;
301  * popup_id and bar_id are for returning the signal handler ids returned by
302  * g_signal_connect; they can be NULL if you don't need to know them */
303 void
304 multi_win_menu_connect_data(MultiWin *win, MenuTreeID id,
305     GCallback handler, gpointer user_data, GConnectFlags flags,
306     gulong *popup_id, gulong *bar_id, gulong *short_pupup_id);
307 
308 inline static void
multi_win_menu_connect(MultiWin * win,MenuTreeID id,GCallback handler,gpointer user_data,gulong * popup_id,gulong * bar_id,gulong * short_popup_id)309 multi_win_menu_connect(MultiWin * win, MenuTreeID id,
310         GCallback handler, gpointer user_data,
311         gulong *popup_id, gulong *bar_id, gulong *short_popup_id)
312 {
313     multi_win_menu_connect_data(win, id, handler, user_data, 0,
314             popup_id, bar_id, short_popup_id);
315 }
316 
317 inline static void
multi_win_menu_connect_swapped(MultiWin * win,MenuTreeID id,GCallback handler,gpointer user_data,gulong * popup_id,gulong * bar_id,gulong * short_popup_id)318 multi_win_menu_connect_swapped(MultiWin * win, MenuTreeID id,
319         GCallback handler, gpointer user_data,
320         gulong *popup_id, gulong *bar_id, gulong *short_popup_id)
321 {
322     multi_win_menu_connect_data(win, id, handler, user_data,
323         G_CONNECT_SWAPPED, popup_id, bar_id, short_popup_id);
324 }
325 
326 MultiTab *multi_win_get_current_tab(MultiWin * win);
327 
328 guint multi_win_get_ntabs(MultiWin * win);
329 
330 gpointer multi_win_get_user_data_for_current_tab(MultiWin * win);
331 
332 MenuTree *multi_win_get_menu_bar(MultiWin * win);
333 
334 MenuTree *multi_win_get_popup_menu(MultiWin * win);
335 
336 MenuTree *multi_win_get_short_popup_menu(MultiWin * win);
337 
338 Options *multi_win_get_shortcut_scheme(MultiWin * win);
339 
340 void multi_win_set_shortcut_scheme(MultiWin * win, Options *);
341 
342 GtkAccelGroup *multi_win_get_accel_group(MultiWin * win);
343 
344 void
345 multi_win_set_show_menu_bar(MultiWin * win, gboolean show);
346 
347 gboolean multi_win_get_show_menu_bar(MultiWin * win);
348 
349 typedef enum {
350     MultiWinScrollBar_None,
351     MultiWinScrollBar_Right,
352     MultiWinScrollBar_Left,
353     MultiWinScrollBar_Query        /* No change, just query current value */
354 } MultiWinScrollBar_Position;
355 
356 /* Sets scrollbar position (will be ignored if already set), and returns the
357  * current value in case the new value had to be ignored */
358 MultiWinScrollBar_Position multi_win_set_scroll_bar_position(MultiWin * win,
359     MultiWinScrollBar_Position new_pos);
360 
361 /* Make sure this win's current tab claims focus for this win */
362 void multi_win_restore_focus(MultiWin *win);
363 
364 /* Ignore toggle signals on menu items because they're being manipulated by
365  * code, not user */
366 void multi_win_set_ignore_toggles(MultiWin *win, gboolean ignore);
367 
368 gboolean multi_win_get_ignore_toggles(MultiWin *win);
369 
370 void multi_win_select_tab(MultiWin *win, MultiTab *tab);
371 
372 void multi_win_set_wrap_switch_tab(MultiWin *win, gboolean wrap);
373 
374 /* Apply a function to all tabs in one window */
375 typedef void (*MultiWinForEachTabFunc)(MultiTab *tab, void *user_data);
376 void multi_win_foreach_tab(MultiWin *, MultiWinForEachTabFunc,
377         gpointer user_data);
378 
379 GtkPositionType multi_win_get_tab_pos(MultiWin *win);
380 
381 gboolean multi_win_get_always_show_tabs(MultiWin *win);
382 
383 void multi_win_set_always_show_tabs(MultiWin *win, gboolean show);
384 
385 gboolean multi_win_get_show_add_tab_button(MultiWin *win);
386 
387 void multi_win_set_show_add_tab_button(MultiWin *win, gboolean show);
388 
389 /* List of all known windows - treat as read-only */
390 extern GList *multi_win_all;
391 
392 /* Sets a title template string. %s is substituted with the current tab's title.
393  * There may only be one %s and no other % characters except %%.
394  * NULL is equivalent to "%s".
395  */
396 void multi_win_set_title_template(MultiWin *win, const char *tt);
397 
398 const char *multi_win_get_title_template(MultiWin *win);
399 
400 const char *multi_win_get_title(MultiWin *win);
401 
402 void multi_win_set_title(MultiWin *win, const char *);
403 
404 void multi_win_set_title_template_locked(MultiWin *win, gboolean locked);
405 
406 gboolean multi_win_get_title_template_locked(MultiWin *win);
407 
408 /* Whether window is managed by a compositor */
409 gboolean multi_win_composite(MultiWin *win);
410 
411 const char *multi_win_get_shortcuts_scheme_name(MultiWin *win);
412 
413 guint multi_win_get_num_tabs(MultiWin *win);
414 
415 /* Parses a geometry string and returns TRUE if successful. If sizes
416  * aren't given their respective outputs are set to 0. xy is updated to indicate
417  * whether x and y were present.
418  */
419 gboolean multi_win_parse_geometry(const char *geom,
420         int *width, int *height, int *x, int *y, gboolean *xy);
421 
422 /* tab may be NULL to use the currently active tab */
423 void multi_win_set_initial_geometry(MultiWin *win, const char *geom,
424         MultiTab *tab);
425 
426 /* tab may be NULL to use the currently active tab */
427 void multi_win_apply_new_geometry(MultiWin *win, int columns, int rows,
428         MultiTab *tab);
429 
430 #endif /* MULTITAB_H */
431 
432 /* vi:set sw=4 ts=4 et cindent cino= */
433