1
/* Metacity X window decorations */
4
* Copyright (C) 2001 Havoc Pennington
5
* Copyright (C) 2003, 2004 Red Hat, Inc.
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.
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.
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
27
#include "keybindings.h"
30
#include <X11/extensions/Xrender.h>
33
#define EVENT_MASK (SubstructureRedirectMask | \
34
StructureNotifyMask | SubstructureNotifyMask | \
36
ButtonPressMask | ButtonReleaseMask | \
37
PointerMotionMask | PointerMotionHintMask | \
38
EnterWindowMask | LeaveWindowMask | \
43
meta_window_ensure_frame (MetaWindow *window)
46
XSetWindowAttributes attrs;
52
/* See comment below for why this is required. */
53
meta_display_grab (window->display);
55
frame = g_new (MetaFrame, 1);
57
frame->window = window;
58
frame->xwindow = None;
60
frame->rect = window->rect;
63
frame->bottom_height = 0;
64
frame->right_width = 0;
65
frame->current_cursor = 0;
67
frame->mapped = FALSE;
68
frame->need_reapply_frame_shape = TRUE;
69
frame->is_flashing = FALSE;
71
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
73
XVisualIDFromVisual (window->xvisual) ==
74
XVisualIDFromVisual (window->screen->default_xvisual) ?
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);
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.
86
* We look for an ARGB visual if we can find one, otherwise use
87
* the default of NULL.
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.
93
if (window->depth == 32)
94
visual = window->xvisual;
98
frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
99
window->display->xdisplay,
105
frame->window->screen->number);
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);
112
meta_display_register_x_window (window->display, &frame->xwindow, window);
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
122
meta_error_trap_push (window->display);
125
window->mapped = FALSE; /* the reparent will unmap the window,
126
* we don't want to take that as a withdraw
128
meta_topic (META_DEBUG_WINDOW_STATE,
129
"Incrementing unmaps_pending on %s for reparent\n", window->desc);
130
window->unmaps_pending += 1;
132
/* window was reparented to this position */
136
XReparentWindow (window->display->xdisplay,
141
/* FIXME handle this error */
142
meta_error_trap_pop (window->display, FALSE);
144
/* stick frame to the window */
145
window->frame = frame;
148
meta_ui_set_frame_title (window->screen->ui,
149
window->frame->xwindow,
152
/* Move keybindings to frame instead of window */
153
meta_window_grab_keys (window);
156
meta_ui_apply_frame_shape (frame->window->screen->ui,
160
frame->window->has_shape);
161
frame->need_reapply_frame_shape = FALSE;
163
meta_display_ungrab (window->display);
167
meta_window_destroy_frame (MetaWindow *window)
171
if (window->frame == NULL)
174
meta_verbose ("Unframing window %s\n", window->desc);
176
frame = window->frame;
178
meta_bell_notify_frame_destroy (frame);
180
/* Unparent the client window; it may be destroyed,
181
* thus the error trap.
183
meta_error_trap_push (window->display);
186
window->mapped = FALSE; /* Keep track of unmapping it, so we
187
* can identify a withdraw initiated
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;
194
XReparentWindow (window->display->xdisplay,
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);
202
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
204
meta_display_unregister_x_window (window->display,
207
window->frame = NULL;
209
/* Move keybindings to window instead of frame */
210
meta_window_grab_keys (window);
214
/* Put our state back where it should be */
215
meta_window_queue_calc_showing (window);
220
meta_frame_get_flags (MetaFrame *frame)
222
MetaFrameFlags flags;
226
if (frame->window->border_only)
228
; /* FIXME this may disable the _function_ as well as decor
229
* in some cases, which is sort of wrong.
234
flags |= META_FRAME_ALLOWS_MENU;
236
if (frame->window->has_close_func)
237
flags |= META_FRAME_ALLOWS_DELETE;
239
if (frame->window->has_maximize_func)
240
flags |= META_FRAME_ALLOWS_MAXIMIZE;
242
if (frame->window->has_minimize_func)
243
flags |= META_FRAME_ALLOWS_MINIMIZE;
245
if (frame->window->has_shade_func)
246
flags |= META_FRAME_ALLOWS_SHADE;
249
if (META_WINDOW_ALLOWS_MOVE (frame->window))
250
flags |= META_FRAME_ALLOWS_MOVE;
252
if (META_WINDOW_ALLOWS_HORIZONTAL_RESIZE (frame->window))
253
flags |= META_FRAME_ALLOWS_HORIZONTAL_RESIZE;
255
if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
256
flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
258
if (frame->window->has_focus)
259
flags |= META_FRAME_HAS_FOCUS;
261
if (frame->window->shaded)
262
flags |= META_FRAME_SHADED;
264
if (frame->window->on_all_workspaces)
265
flags |= META_FRAME_STUCK;
267
if (frame->window->maximized)
268
flags |= META_FRAME_MAXIMIZED;
270
if (frame->window->fullscreen)
271
flags |= META_FRAME_FULLSCREEN;
273
if (frame->is_flashing)
274
flags |= META_FRAME_IS_FLASHING;
280
meta_frame_calc_geometry (MetaFrame *frame,
281
MetaFrameGeometry *geomp)
283
MetaFrameGeometry geom;
286
window = frame->window;
288
meta_ui_get_frame_geometry (window->screen->ui,
299
update_shape (MetaFrame *frame)
301
if (frame->need_reapply_frame_shape)
303
meta_ui_apply_frame_shape (frame->window->screen->ui,
307
frame->window->has_shape);
308
frame->need_reapply_frame_shape = FALSE;
313
meta_frame_sync_to_window (MetaFrame *frame,
316
gboolean need_resize)
318
if (!(need_move || need_resize))
320
update_shape (frame);
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);
331
/* set bg to none to avoid flicker */
334
meta_ui_unflicker_frame_bg (frame->window->screen->ui,
339
/* we need new shape if we're resized */
340
frame->need_reapply_frame_shape = TRUE;
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.
349
update_shape (frame);
351
meta_ui_move_resize_frame (frame->window->screen->ui,
360
meta_ui_reset_frame_bg (frame->window->screen->ui,
363
/* If we're interactively resizing the frame, repaint
364
* it immediately so we don't start to lag.
366
if (frame->window->display->grab_window ==
368
meta_ui_repaint_frame (frame->window->screen->ui,
374
meta_frame_queue_draw (MetaFrame *frame)
376
meta_ui_queue_frame_draw (frame->window->screen->ui,
381
meta_frame_set_screen_cursor (MetaFrame *frame,
385
if (cursor == frame->current_cursor)
387
frame->current_cursor = cursor;
388
if (cursor == META_CURSOR_DEFAULT)
389
XUndefineCursor (frame->window->display->xdisplay, frame->xwindow);
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);