~muktupavels/metacity/adwaita-icon-theme-lp-1414613

« back to all changes in this revision

Viewing changes to src/frame.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-10-03 22:44:28 UTC
  • mfrom: (1.2.1 upstream) (2.1.1 sarge)
  • Revision ID: james.westby@ubuntu.com-20051003224428-ft31gkmz12qpzohj
Tags: 1:2.12.1-0ubuntu1
* New upstream release:
  - Thanks to Ray Strode, Havoc Pennington, and Elijah Newren for
    improvements in this release.
  - Truncate ridiculously long titles to avoid crashing or letting the
    pager crash (Ray, Havoc, Elijah) [#315070] (Ubuntu: #15995)
  - Get the tabbing window outline to work with gtk+ 2.8.4 again
    (Elijah) [#317528] (Ubuntu: #16589)
  - Translations: Mahay Alam Khan (bn), Francisco Javier F. Serrador (es), 
    Ivar Smolin (et), I\uffffaki Larra\uffffaga Murgoitio (eu), Luca 
    Ferretti (it), Christian Rose (sv), Clytie Siddall (vi), Funda 
    Wang (zh_CN)
* debian/control.in:
  - Bumped Standards-Version.
* debian/patches/003_bordersdrawingfix.patch:
  - dropped, fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Metacity X window decorations */
 
2
 
 
3
/* 
 
4
 * Copyright (C) 2001 Havoc Pennington
 
5
 * Copyright (C) 2003, 2004 Red Hat, Inc.
 
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 as
 
9
 * published by the Free Software Foundation; either version 2 of the
 
10
 * License, or (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * 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
 
20
 * 02111-1307, USA.
 
21
 */
 
22
 
 
23
#include <config.h>
 
24
#include "frame.h"
 
25
#include "bell.h"
 
26
#include "errors.h"
 
27
#include "keybindings.h"
 
28
 
 
29
#ifdef HAVE_RENDER
 
30
#include <X11/extensions/Xrender.h>
 
31
#endif
 
32
 
 
33
#define EVENT_MASK (SubstructureRedirectMask |                     \
 
34
                    StructureNotifyMask | SubstructureNotifyMask | \
 
35
                    ExposureMask |                                 \
 
36
                    ButtonPressMask | ButtonReleaseMask |          \
 
37
                    PointerMotionMask | PointerMotionHintMask |    \
 
38
                    EnterWindowMask | LeaveWindowMask |            \
 
39
                    FocusChangeMask |                              \
 
40
                    ColormapChangeMask)
 
41
 
 
42
void
 
43
meta_window_ensure_frame (MetaWindow *window)
 
44
{
 
45
  MetaFrame *frame;
 
46
  XSetWindowAttributes attrs;
 
47
  Visual *visual;
 
48
  
 
49
  if (window->frame)
 
50
    return;
 
51
  
 
52
  /* See comment below for why this is required. */
 
53
  meta_display_grab (window->display);
 
54
  
 
55
  frame = g_new (MetaFrame, 1);
 
56
 
 
57
  frame->window = window;
 
58
  frame->xwindow = None;
 
59
 
 
60
  frame->rect = window->rect;
 
61
  frame->child_x = 0;
 
62
  frame->child_y = 0;
 
63
  frame->bottom_height = 0;
 
64
  frame->right_width = 0;
 
65
  frame->current_cursor = 0;
 
66
 
 
67
  frame->mapped = FALSE;
 
68
  frame->need_reapply_frame_shape = TRUE;
 
69
  frame->is_flashing = FALSE;
 
70
  
 
71
  meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
 
72
                window->desc,
 
73
                XVisualIDFromVisual (window->xvisual) ==
 
74
                XVisualIDFromVisual (window->screen->default_xvisual) ?
 
75
                "is" : "is not",
 
76
                window->depth, window->screen->default_depth);
 
77
  meta_verbose ("Frame geometry %d,%d  %dx%d\n",
 
78
                frame->rect.x, frame->rect.y,
 
79
                frame->rect.width, frame->rect.height);
 
80
  
 
81
  /* Default depth/visual handles clients with weird visuals; they can
 
82
   * always be children of the root depth/visual obviously, but
 
83
   * e.g. DRI games can't be children of a parent that has the same
 
84
   * visual as the client. NULL means default visual.
 
85
   *
 
86
   * We look for an ARGB visual if we can find one, otherwise use
 
87
   * the default of NULL.
 
88
   */
 
89
  
 
90
  /* Special case for depth 32 windows (assumed to be ARGB),
 
91
   * we use the window's visual. Otherwise we just use the system visual.
 
92
   */
 
93
  if (window->depth == 32)
 
94
    visual = window->xvisual;
 
95
  else
 
96
    visual = NULL;
 
97
  
 
98
  frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
 
99
                                                window->display->xdisplay,
 
100
                                                visual,
 
101
                                                frame->rect.x,
 
102
                                                frame->rect.y,
 
103
                                                frame->rect.width,
 
104
                                                frame->rect.height,
 
105
                                                frame->window->screen->number);
 
106
 
 
107
  meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
 
108
  attrs.event_mask = EVENT_MASK;
 
109
  XChangeWindowAttributes (window->display->xdisplay,
 
110
                           frame->xwindow, CWEventMask, &attrs);
 
111
  
 
112
  meta_display_register_x_window (window->display, &frame->xwindow, window);
 
113
 
 
114
  /* Reparent the client window; it may be destroyed,
 
115
   * thus the error trap. We'll get a destroy notify later
 
116
   * and free everything. Comment in FVWM source code says
 
117
   * we need a server grab or the child can get its MapNotify
 
118
   * before we've finished reparenting and getting the decoration
 
119
   * window onscreen, so ensure_frame must be called with
 
120
   * a grab.
 
121
   */
 
122
  meta_error_trap_push (window->display);
 
123
  if (window->mapped)
 
124
    {
 
125
      window->mapped = FALSE; /* the reparent will unmap the window,
 
126
                               * we don't want to take that as a withdraw
 
127
                               */
 
128
      meta_topic (META_DEBUG_WINDOW_STATE,
 
129
                  "Incrementing unmaps_pending on %s for reparent\n", window->desc);
 
130
      window->unmaps_pending += 1;
 
131
    }
 
132
  /* window was reparented to this position */
 
133
  window->rect.x = 0;
 
134
  window->rect.y = 0;
 
135
 
 
136
  XReparentWindow (window->display->xdisplay,
 
137
                   window->xwindow,
 
138
                   frame->xwindow,
 
139
                   window->rect.x,
 
140
                   window->rect.y);
 
141
  /* FIXME handle this error */
 
142
  meta_error_trap_pop (window->display, FALSE);
 
143
  
 
144
  /* stick frame to the window */
 
145
  window->frame = frame;
 
146
  
 
147
  if (window->title)
 
148
    meta_ui_set_frame_title (window->screen->ui,
 
149
                             window->frame->xwindow,
 
150
                             window->title);
 
151
 
 
152
  /* Move keybindings to frame instead of window */
 
153
  meta_window_grab_keys (window);
 
154
 
 
155
  /* Shape mask */
 
156
  meta_ui_apply_frame_shape (frame->window->screen->ui,
 
157
                             frame->xwindow,
 
158
                             frame->rect.width,
 
159
                             frame->rect.height,
 
160
                             frame->window->has_shape);
 
161
  frame->need_reapply_frame_shape = FALSE;
 
162
  
 
163
  meta_display_ungrab (window->display);
 
164
}
 
165
 
 
166
void
 
167
meta_window_destroy_frame (MetaWindow *window)
 
168
{
 
169
  MetaFrame *frame;
 
170
  
 
171
  if (window->frame == NULL)
 
172
    return;
 
173
 
 
174
  meta_verbose ("Unframing window %s\n", window->desc);
 
175
  
 
176
  frame = window->frame;
 
177
  
 
178
  meta_bell_notify_frame_destroy (frame);
 
179
  
 
180
  /* Unparent the client window; it may be destroyed,
 
181
   * thus the error trap.
 
182
   */
 
183
  meta_error_trap_push (window->display);
 
184
  if (window->mapped)
 
185
    {
 
186
      window->mapped = FALSE; /* Keep track of unmapping it, so we
 
187
                               * can identify a withdraw initiated
 
188
                               * by the client.
 
189
                               */
 
190
      meta_topic (META_DEBUG_WINDOW_STATE,
 
191
                  "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
 
192
      window->unmaps_pending += 1;
 
193
    }
 
194
  XReparentWindow (window->display->xdisplay,
 
195
                   window->xwindow,
 
196
                   window->screen->xroot,
 
197
                   /* FIXME where to put it back depends on the gravity */
 
198
                   window->frame->rect.x,
 
199
                   window->frame->rect.y);
 
200
  meta_error_trap_pop (window->display, FALSE);
 
201
 
 
202
  meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
 
203
 
 
204
  meta_display_unregister_x_window (window->display,
 
205
                                    frame->xwindow);
 
206
  
 
207
  window->frame = NULL;
 
208
 
 
209
  /* Move keybindings to window instead of frame */
 
210
  meta_window_grab_keys (window);
 
211
  
 
212
  g_free (frame);
 
213
  
 
214
  /* Put our state back where it should be */
 
215
  meta_window_queue_calc_showing (window);
 
216
}
 
217
 
 
218
 
 
219
MetaFrameFlags
 
220
meta_frame_get_flags (MetaFrame *frame)
 
221
{
 
222
  MetaFrameFlags flags;
 
223
 
 
224
  flags = 0;
 
225
 
 
226
  if (frame->window->border_only)
 
227
    {
 
228
      ; /* FIXME this may disable the _function_ as well as decor
 
229
         * in some cases, which is sort of wrong.
 
230
         */
 
231
    }
 
232
  else
 
233
    {
 
234
      flags |= META_FRAME_ALLOWS_MENU;
 
235
      
 
236
      if (frame->window->has_close_func)
 
237
        flags |= META_FRAME_ALLOWS_DELETE;
 
238
      
 
239
      if (frame->window->has_maximize_func)
 
240
        flags |= META_FRAME_ALLOWS_MAXIMIZE;
 
241
      
 
242
      if (frame->window->has_minimize_func)
 
243
        flags |= META_FRAME_ALLOWS_MINIMIZE;
 
244
      
 
245
      if (frame->window->has_shade_func)
 
246
        flags |= META_FRAME_ALLOWS_SHADE;
 
247
    }  
 
248
  
 
249
  if (META_WINDOW_ALLOWS_MOVE (frame->window))
 
250
    flags |= META_FRAME_ALLOWS_MOVE;
 
251
 
 
252
  if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window))
 
253
    flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE;
 
254
 
 
255
  if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
 
256
    flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
 
257
  
 
258
  if (frame->window->has_focus)
 
259
    flags |= META_FRAME_HAS_FOCUS;
 
260
 
 
261
  if (frame->window->shaded)
 
262
    flags |= META_FRAME_SHADED;
 
263
 
 
264
  if (frame->window->on_all_workspaces)
 
265
    flags |= META_FRAME_STUCK;
 
266
 
 
267
  if (frame->window->maximized)
 
268
    flags |= META_FRAME_MAXIMIZED;
 
269
 
 
270
  if (frame->window->fullscreen)
 
271
    flags |= META_FRAME_FULLSCREEN;
 
272
 
 
273
  if (frame->is_flashing)
 
274
    flags |= META_FRAME_IS_FLASHING;
 
275
 
 
276
  return flags;
 
277
}
 
278
 
 
279
void
 
280
meta_frame_calc_geometry (MetaFrame         *frame,
 
281
                          MetaFrameGeometry *geomp)
 
282
{
 
283
  MetaFrameGeometry geom;
 
284
  MetaWindow *window;
 
285
 
 
286
  window = frame->window;
 
287
 
 
288
  meta_ui_get_frame_geometry (window->screen->ui,
 
289
                              frame->xwindow,
 
290
                              &geom.top_height,
 
291
                              &geom.bottom_height,
 
292
                              &geom.left_width,
 
293
                              &geom.right_width);
 
294
  
 
295
  *geomp = geom;
 
296
}
 
297
 
 
298
static void
 
299
update_shape (MetaFrame *frame)
 
300
{
 
301
  if (frame->need_reapply_frame_shape)
 
302
    {
 
303
      meta_ui_apply_frame_shape (frame->window->screen->ui,
 
304
                                 frame->xwindow,
 
305
                                 frame->rect.width,
 
306
                                 frame->rect.height,
 
307
                                 frame->window->has_shape);
 
308
      frame->need_reapply_frame_shape = FALSE;
 
309
    }
 
310
}
 
311
 
 
312
void
 
313
meta_frame_sync_to_window (MetaFrame *frame,
 
314
                           int        resize_gravity,
 
315
                           gboolean   need_move,
 
316
                           gboolean   need_resize)
 
317
{
 
318
  if (!(need_move || need_resize))
 
319
    {
 
320
      update_shape (frame);
 
321
      return;
 
322
    }
 
323
 
 
324
  meta_topic (META_DEBUG_GEOMETRY,
 
325
              "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)\n",
 
326
              frame->rect.x, frame->rect.y,
 
327
              frame->rect.width, frame->rect.height,
 
328
              frame->rect.x + frame->rect.width,
 
329
              frame->rect.y + frame->rect.height);
 
330
 
 
331
  /* set bg to none to avoid flicker */
 
332
  if (need_resize)
 
333
    {
 
334
      meta_ui_unflicker_frame_bg (frame->window->screen->ui,
 
335
                                  frame->xwindow,
 
336
                                  frame->rect.width,
 
337
                                  frame->rect.height);
 
338
 
 
339
      /* we need new shape if we're resized */
 
340
      frame->need_reapply_frame_shape = TRUE;
 
341
    }
 
342
 
 
343
  /* Done before the window resize, because doing it before means
 
344
   * part of the window being resized becomes unshaped, which may
 
345
   * be sort of hard to see with bg = None. If we did it after
 
346
   * window resize, part of the window being resized would become
 
347
   * shaped, which might be more visible.
 
348
   */
 
349
  update_shape (frame);
 
350
  
 
351
  meta_ui_move_resize_frame (frame->window->screen->ui,
 
352
                             frame->xwindow,
 
353
                             frame->rect.x,
 
354
                             frame->rect.y,
 
355
                             frame->rect.width,
 
356
                             frame->rect.height);
 
357
 
 
358
  if (need_resize)
 
359
    {
 
360
      meta_ui_reset_frame_bg (frame->window->screen->ui,
 
361
                              frame->xwindow);
 
362
 
 
363
      /* If we're interactively resizing the frame, repaint
 
364
       * it immediately so we don't start to lag.
 
365
       */
 
366
      if (frame->window->display->grab_window ==
 
367
          frame->window)
 
368
        meta_ui_repaint_frame (frame->window->screen->ui,
 
369
                               frame->xwindow);
 
370
    }
 
371
}
 
372
 
 
373
void
 
374
meta_frame_queue_draw (MetaFrame *frame)
 
375
{
 
376
  meta_ui_queue_frame_draw (frame->window->screen->ui,
 
377
                            frame->xwindow);
 
378
}
 
379
 
 
380
void
 
381
meta_frame_set_screen_cursor (MetaFrame *frame,
 
382
                              MetaCursor cursor)
 
383
{
 
384
  Cursor xcursor;
 
385
  if (cursor == frame->current_cursor)
 
386
    return;
 
387
  frame->current_cursor = cursor;
 
388
  if (cursor == META_CURSOR_DEFAULT)
 
389
    XUndefineCursor (frame->window->display->xdisplay, frame->xwindow);
 
390
  else
 
391
    { 
 
392
      xcursor = meta_display_create_x_cursor (frame->window->display, cursor);
 
393
      XDefineCursor (frame->window->display->xdisplay, frame->xwindow, xcursor);
 
394
      XFlush (frame->window->display->xdisplay);
 
395
      XFreeCursor (frame->window->display->xdisplay, xcursor);
 
396
    }
 
397
}
 
398