summaryrefslogtreecommitdiff
path: root/src/core/stack.h
blob: a33fac45fe4276bfcaf17fae237c2dd86f0752cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */

/*
 * Copyright (C) 2001 Havoc Pennington
 * Copyright (C) 2005 Elijah Newren
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef META_STACK_H
#define META_STACK_H

/**
 * SECTION:stack
 * @short_description: Which windows cover which other windows
 *
 * There are two factors that determine window position.
 *
 * One is window->stack_position, which is a unique integer
 * indicating how windows are ordered with respect to one
 * another. The ordering here transcends layers; it isn't changed
 * as the window is moved among layers. This allows us to move several
 * windows from one layer to another, while preserving the relative
 * order of the moved windows. Also, it allows us to restore
 * the stacking order from a saved session.
 *
 * However when actually stacking windows on the screen, the
 * layer overrides the stack_position; windows are first sorted
 * by layer, then by stack_position within each layer.
 */

#include "core/display-private.h"

/**
 * A sorted list of windows bearing some level of resemblance to the stack of
 * windows on the X server.
 *
 * (This is only used as a field within a MetaScreen; we treat it as a separate
 * class for simplicity.)
 */
struct _MetaStack
{
  GObject parent;

  /** The MetaDisplay containing this stack. */
  MetaDisplay *display;

  /** The MetaWindows of the windows we manage, sorted in order. */
  GList *sorted;

  /**
   * If this is zero, the local stack oughtn't to be brought up to date with
   * the X server's stack, because it is in the middle of being updated.
   * If it is positive, the local stack is said to be "frozen", and will need
   * to be thawed that many times before the stack can be brought up to date
   * again.  You may freeze the stack with meta_stack_freeze() and thaw it
   * with meta_stack_thaw().
   */
  int freeze_count;

  /**
   * The last-known stack of all windows, bottom to top.  We cache it here
   * so that subsequent times we'll be able to do incremental moves.
   */
  GArray *last_all_root_children_stacked;

  /**
   * Number of stack positions; same as the length of added, but
   * kept for quick reference.
   */
  gint n_positions;

  /** Is the stack in need of re-sorting? */
  unsigned int need_resort : 1;

  /**
   * Are the windows in the stack in need of having their
   * layers recalculated?
   */
  unsigned int need_relayer : 1;

  /**
   * Are the windows in the stack in need of having their positions
   * recalculated with respect to transiency (parent and child windows)?
   */
  unsigned int need_constrain : 1;
};

#define META_TYPE_STACK (meta_stack_get_type ())
G_DECLARE_FINAL_TYPE (MetaStack, meta_stack, META, STACK, GObject)

/**
 * meta_stack_new:
 * @display: The MetaDisplay which will be the parent of this stack.
 *
 * Creates and initialises a MetaStack.
 *
 * Returns: The new stack.
 */
MetaStack * meta_stack_new (MetaDisplay *display);

/**
 * meta_stack_add:
 * @stack: The stack to add it to
 * @window: The window to add
 *
 * Adds a window to the local stack.  It is a fatal error to call this
 * function on a window which already exists on the stack of any screen.
 */
void       meta_stack_add (MetaStack  *stack,
                           MetaWindow *window);

/**
 * meta_stack_remove:
 * @stack: The stack to remove it from
 * @window: The window to remove
 *
 * Removes a window from the local stack.  It is a fatal error to call this
 * function on a window which exists on the stack of any screen.
 */
void       meta_stack_remove (MetaStack  *stack,
                              MetaWindow *window);
/**
 * meta_stack_update_layer:
 * @stack: The stack to recalculate
 * @window: Dummy parameter
 *
 * Recalculates the correct layer for all windows in the stack,
 * and moves them about accordingly.
 *
 */
void       meta_stack_update_layer (MetaStack  *stack,
                                    MetaWindow *window);

/**
 * meta_stack_update_transient:
 * @stack: The stack to recalculate
 * @window: Dummy parameter
 *
 * Recalculates the correct stacking order for all windows in the stack
 * according to their transience, and moves them about accordingly.
 *
 * FIXME: What's with the dummy parameter?
 */
void       meta_stack_update_transient (MetaStack  *stack,
                                        MetaWindow *window);

/**
 * meta_stack_raise:
 * @stack: The stack to modify.
 * @window: The window that's making an ascension.
 *              (Amulet of Yendor not required.)
 *
 * Move a window to the top of its layer.
 */
void       meta_stack_raise (MetaStack  *stack,
                             MetaWindow *window);
/**
 * meta_stack_lower:
 * @stack: The stack to modify.
 * @window: The window that's on the way downwards.
 *
 * Move a window to the bottom of its layer.
 */
void       meta_stack_lower (MetaStack  *stack,
                             MetaWindow *window);

/**
 * meta_stack_freeze:
 * @stack: The stack to freeze.
 *
 * Prevent syncing to server until the next call of meta_stack_thaw(),
 * so that we can carry out multiple operations in one go without having
 * everything halfway reflected on the X server.
 *
 * (Calls to meta_stack_freeze() nest, so that multiple calls to
 * meta_stack_freeze will require multiple calls to meta_stack_thaw().)
 */
void       meta_stack_freeze (MetaStack *stack);

/**
 * meta_stack_thaw:
 * @stack: The stack to thaw.
 *
 * Undoes a meta_stack_freeze(), and processes anything which has become
 * necessary during the freeze.  It is an error to call this function if
 * the stack has not been frozen.
 */
void        meta_stack_thaw (MetaStack *stack);

/**
 * meta_stack_get_top:
 * @stack: The stack to examine.
 *
 * Finds the top window on the stack.
 *
 * Returns: The top window on the stack, or %NULL in the vanishingly unlikely
 *          event that you have no windows on your screen whatsoever.
 */
MetaWindow * meta_stack_get_top (MetaStack  *stack);

/**
 * meta_stack_get_bottom:
 * @stack: The stack to search
 *
 * Finds the window at the bottom of the stack.  Since that's pretty much
 * always the desktop, this isn't the most useful of functions, and nobody
 * actually calls it.  We should probably get rid of it.
 */
MetaWindow * meta_stack_get_bottom (MetaStack  *stack);

/**
 * meta_stack_get_above:
 * @stack: The stack to search.
 * @window: The window to look above.
 * @only_within_layer: If %TRUE, will return %NULL if @window is the
 *                     top window in its layer.
 *
 * Finds the window above a given window in the stack.
 * It is not an error to pass in a window which does not exist in
 * the stack; the function will merely return %NULL.
 *
 * Returns: %NULL if there is no such window;
 *          the window above @window otherwise.
 */
MetaWindow * meta_stack_get_above (MetaStack  *stack,
                                   MetaWindow *window,
                                   gboolean    only_within_layer);

/**
 * meta_stack_get_below:
 * @stack: The stack to search.
 * @window: The window to look below.
 * @only_within_layer: If %TRUE, will return %NULL if window is the
 *                     bottom window in its layer.
 *
 * Finds the window below a given window in the stack.
 * It is not an error to pass in a window which does not exist in
 * the stack; the function will merely return %NULL.
 *
 *
 * Returns: %NULL if there is no such window;
 *          the window below @window otherwise.
 */
MetaWindow * meta_stack_get_below (MetaStack  *stack,
                                   MetaWindow *window,
                                   gboolean    only_within_layer);

/**
 * meta_stack_list_windows:
 * @stack: The stack to examine.
 * @workspace: If not %NULL, only windows on this workspace will be
 *             returned; otherwise all windows in the stack will be
 *             returned.
 *
 * Finds all the windows in the stack, in order.
 *
 * Returns: (transfer container) (element-type Meta.Window):
 *     A list of windows, in stacking order, honouring layers.
 */
GList * meta_stack_list_windows (MetaStack     *stack,
                                 MetaWorkspace *workspace);

/**
 * meta_stack_windows_cmp:
 * @stack: A stack containing both window_a and window_b
 * @window_a: A window
 * @window_b  Another window
 *
 * Comparison function for windows within a stack.  This is not directly
 * suitable for use within a standard comparison routine, because it takes
 * an extra parameter; you will need to wrap it.
 *
 * (FIXME: We could remove the stack parameter and use the stack of
 * the screen of window A, and complain if the stack of the screen of
 * window B differed; then this would be a usable general comparison function.)
 *
 * (FIXME: Apparently identical to compare_window_position(). Merge them.)
 *
 * \return -1 if window_a is below window_b, honouring layers; 1 if it's
 *         above it; 0 if you passed in the same window twice!
 */
int meta_stack_windows_cmp (MetaStack  *stack,
                            MetaWindow *window_a,
                            MetaWindow *window_b);

/**
 * meta_window_set_stack_position:
 * @window: The window which is moving.
 * @position:  Where it should move to (0 is the bottom).
 *
 * Sets the position of a window within the stack.  This will only move it
 * up or down within its layer.  It is an error to attempt to move this
 * below position zero or above the last position in the stack (however, since
 * we don't provide a simple way to tell the number of windows in the stack,
 * this requirement may not be easy to fulfil).
 */
void meta_window_set_stack_position (MetaWindow *window,
                                     int         position);

/**
 * meta_stack_get_positions:
 * @stack: The stack to examine.
 *
 * Returns the current stack state, allowing rudimentary transactions.
 *
 * Returns: (transfer container) (element-type Meta.Window):
 *          An opaque #GList representing the current stack sort order;
 *          it is the caller's responsibility to free it.
 *          Pass this to meta_stack_set_positions() later if you want to restore
 *          the state to where it was when you called this function.
 */
GList * meta_stack_get_positions (MetaStack *stack);

/**
 * meta_stack_set_positions:
 * @stack:  The stack to roll back.
 * @windows:  The list returned from meta_stack_get_positions().
 *
 * Rolls back a transaction, given the list returned from
 * meta_stack_get_positions().
 *
 */
void meta_stack_set_positions (MetaStack *stack,
                               GList     *windows);

void meta_stack_update_window_tile_matches (MetaStack     *stack,
                                            MetaWorkspace *workspace);

#endif