2
* Copyright © 2005 Novell, Inc.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Novell, Inc. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Novell, Inc. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Author: David Reveman <davidr@novell.com>
29
#include <X11/Xatom.h>
30
#include <X11/Xproto.h>
31
#include <X11/extensions/shape.h>
41
#include <boost/bind.hpp>
43
#include <core/core.h>
44
#include <core/icon.h>
45
#include <core/atoms.h>
46
#include "privatewindow.h"
47
#include "privatescreen.h"
49
PluginClassStorage::Indices windowPluginClassIndices (0);
52
CompWindow::allocPluginClassIndex ()
54
unsigned int i = PluginClassStorage::allocatePluginClassIndex (windowPluginClassIndices);
56
foreach (CompWindow *w, screen->windows ())
57
if (windowPluginClassIndices.size () != w->pluginClasses.size ())
58
w->pluginClasses.resize (windowPluginClassIndices.size ());
64
CompWindow::freePluginClassIndex (unsigned int index)
66
PluginClassStorage::freePluginClassIndex (windowPluginClassIndices, index);
68
foreach (CompWindow *w, ::screen->windows ())
69
if (windowPluginClassIndices.size () != w->pluginClasses.size ())
70
w->pluginClasses.resize (windowPluginClassIndices.size ());
74
PrivateWindow::isAncestorTo (CompWindow *transient,
77
if (transient->priv->transientFor)
79
if (transient->priv->transientFor == ancestor->priv->id)
82
transient = screen->findWindow (transient->priv->transientFor);
84
return isAncestorTo (transient, ancestor);
91
PrivateWindow::recalcNormalHints ()
95
#warning fixme to max Texture size
97
maxSize -= serverGeometry.border () * 2;
99
sizeHints.x = serverGeometry.x ();
100
sizeHints.y = serverGeometry.y ();
101
sizeHints.width = serverGeometry.width ();
102
sizeHints.height = serverGeometry.height ();
104
if (!(sizeHints.flags & PBaseSize))
106
if (sizeHints.flags & PMinSize)
108
sizeHints.base_width = sizeHints.min_width;
109
sizeHints.base_height = sizeHints.min_height;
113
sizeHints.base_width = 0;
114
sizeHints.base_height = 0;
117
sizeHints.flags |= PBaseSize;
120
if (!(sizeHints.flags & PMinSize))
122
sizeHints.min_width = sizeHints.base_width;
123
sizeHints.min_height = sizeHints.base_height;
124
sizeHints.flags |= PMinSize;
127
if (!(sizeHints.flags & PMaxSize))
129
sizeHints.max_width = 65535;
130
sizeHints.max_height = 65535;
131
sizeHints.flags |= PMaxSize;
134
if (sizeHints.max_width < sizeHints.min_width)
135
sizeHints.max_width = sizeHints.min_width;
137
if (sizeHints.max_height < sizeHints.min_height)
138
sizeHints.max_height = sizeHints.min_height;
140
if (sizeHints.min_width < 1)
141
sizeHints.min_width = 1;
143
if (sizeHints.max_width < 1)
144
sizeHints.max_width = 1;
146
if (sizeHints.min_height < 1)
147
sizeHints.min_height = 1;
149
if (sizeHints.max_height < 1)
150
sizeHints.max_height = 1;
152
if (sizeHints.max_width > maxSize)
153
sizeHints.max_width = maxSize;
155
if (sizeHints.max_height > maxSize)
156
sizeHints.max_height = maxSize;
158
if (sizeHints.min_width > maxSize)
159
sizeHints.min_width = maxSize;
161
if (sizeHints.min_height > maxSize)
162
sizeHints.min_height = maxSize;
164
if (sizeHints.base_width > maxSize)
165
sizeHints.base_width = maxSize;
167
if (sizeHints.base_height > maxSize)
168
sizeHints.base_height = maxSize;
170
if (sizeHints.flags & PResizeInc)
172
if (sizeHints.width_inc == 0)
173
sizeHints.width_inc = 1;
175
if (sizeHints.height_inc == 0)
176
sizeHints.height_inc = 1;
180
sizeHints.width_inc = 1;
181
sizeHints.height_inc = 1;
182
sizeHints.flags |= PResizeInc;
185
if (sizeHints.flags & PAspect)
187
/* don't divide by 0 */
188
if (sizeHints.min_aspect.y < 1)
189
sizeHints.min_aspect.y = 1;
191
if (sizeHints.max_aspect.y < 1)
192
sizeHints.max_aspect.y = 1;
196
sizeHints.min_aspect.x = 1;
197
sizeHints.min_aspect.y = 65535;
198
sizeHints.max_aspect.x = 65535;
199
sizeHints.max_aspect.y = 1;
200
sizeHints.flags |= PAspect;
203
if (!(sizeHints.flags & PWinGravity))
205
sizeHints.win_gravity = NorthWestGravity;
206
sizeHints.flags |= PWinGravity;
211
PrivateWindow::updateNormalHints ()
216
status = XGetWMNormalHints (screen->dpy (), priv->id,
217
&priv->sizeHints, &supplied);
220
priv->sizeHints.flags = 0;
222
priv->recalcNormalHints ();
226
PrivateWindow::updateWmHints ()
230
bool iconChanged = false;
233
dFlags = hints->flags;
237
newHints = XGetWMHints (screen->dpy (), id);
240
dFlags ^= newHints->flags;
242
if (newHints->flags & InputHint)
243
inputHint = newHints->input;
247
if ((newHints->flags & IconPixmapHint) &&
248
(hints->icon_pixmap != newHints->icon_pixmap))
252
else if ((newHints->flags & IconMaskHint) &&
253
(hints->icon_mask != newHints->icon_mask))
260
iconChanged |= (dFlags & (IconPixmapHint | IconMaskHint));
272
PrivateWindow::updateClassHints ()
274
XClassHint classHint;
279
free (priv->resName);
280
priv->resName = NULL;
285
free (priv->resClass);
286
priv->resClass = NULL;
289
status = XGetClassHint (screen->dpy (),
290
priv->id, &classHint);
293
if (classHint.res_name)
295
priv->resName = strdup (classHint.res_name);
296
XFree (classHint.res_name);
299
if (classHint.res_class)
301
priv->resClass = strdup (classHint.res_class);
302
XFree (classHint.res_class);
308
PrivateWindow::updateTransientHint ()
313
priv->transientFor = None;
315
status = XGetTransientForHint (screen->dpy (),
316
priv->id, &transientFor);
320
CompWindow *ancestor;
322
ancestor = screen->findWindow (transientFor);
326
/* protect against circular transient dependencies */
327
if (transientFor == priv->id ||
328
PrivateWindow::isAncestorTo (ancestor, window))
331
priv->transientFor = transientFor;
336
PrivateWindow::updateIconGeometry ()
340
unsigned long n, left;
343
priv->iconGeometry.setGeometry (0, 0, 0, 0);
345
result = XGetWindowProperty (screen->dpy (), priv->id,
346
Atoms::wmIconGeometry,
347
0L, 1024L, False, XA_CARDINAL,
348
&actual, &format, &n, &left, &data);
350
if (result == Success && data)
354
unsigned long *geometry = (unsigned long *) data;
356
priv->iconGeometry.setX (geometry[0]);
357
priv->iconGeometry.setY (geometry[1]);
358
priv->iconGeometry.setWidth (geometry[2]);
359
priv->iconGeometry.setHeight (geometry[3]);
367
PrivateWindow::getClientLeaderOfAncestor ()
371
CompWindow *w = screen->findWindow (transientFor);
374
if (w->priv->clientLeader)
375
return w->priv->clientLeader;
377
return w->priv->getClientLeaderOfAncestor ();
385
PrivateWindow::getClientLeader ()
389
unsigned long n, left;
392
result = XGetWindowProperty (screen->dpy (), priv->id,
393
Atoms::wmClientLeader,
394
0L, 1L, False, XA_WINDOW, &actual, &format,
397
if (result == Success && data)
402
memcpy (&win, data, sizeof (Window));
404
XFree ((void *) data);
410
return priv->getClientLeaderOfAncestor ();
414
PrivateWindow::getStartupId ()
418
unsigned long n, left;
421
result = XGetWindowProperty (screen->dpy (), priv->id,
428
if (result == Success && data)
433
id = strdup ((char *) data);
434
XFree ((void *) data);
443
PrivateWindow::setFullscreenMonitors (CompFullscreenMonitorSet *monitors)
445
bool hadFsMonitors = fullscreenMonitorsSet;
446
unsigned int outputs = screen->outputDevs ().size ();
448
fullscreenMonitorsSet = false;
451
(unsigned int) monitors->left < outputs &&
452
(unsigned int) monitors->right < outputs &&
453
(unsigned int) monitors->top < outputs &&
454
(unsigned int) monitors->bottom < outputs)
456
CompRect fsRect (screen->outputDevs ()[monitors->left].x1 (),
457
screen->outputDevs ()[monitors->top].y1 (),
458
screen->outputDevs ()[monitors->right].x2 (),
459
screen->outputDevs ()[monitors->bottom].y2 ());
461
if (fsRect.x1 () < fsRect.x2 () && fsRect.y1 () < fsRect.y2 ())
463
fullscreenMonitorsSet = true;
464
fullscreenMonitorRect = fsRect;
468
if (fullscreenMonitorsSet)
472
data[0] = monitors->top;
473
data[1] = monitors->bottom;
474
data[2] = monitors->left;
475
data[3] = monitors->right;
477
XChangeProperty (screen->dpy (), id, Atoms::wmFullscreenMonitors,
478
XA_CARDINAL, 32, PropModeReplace,
479
(unsigned char *) data, 4);
481
else if (hadFsMonitors)
483
XDeleteProperty (screen->dpy (), id, Atoms::wmFullscreenMonitors);
486
if (state & CompWindowStateFullscreenMask)
487
if (fullscreenMonitorsSet || hadFsMonitors)
488
window->updateAttributes (CompStackingUpdateModeNone);
492
CompWindow::changeState (unsigned int newState)
494
unsigned int oldState;
496
if (priv->state == newState)
499
oldState = priv->state;
500
priv->state = newState;
506
screen->priv->setWindowState (priv->state, priv->id);
508
stateChangeNotify (oldState);
509
screen->matchPropertyChanged (this);
513
setWindowActions (CompScreen *s,
514
unsigned int actions,
520
if (actions & CompWindowActionMoveMask)
521
data[i++] = Atoms::winActionMove;
522
if (actions & CompWindowActionResizeMask)
523
data[i++] = Atoms::winActionResize;
524
if (actions & CompWindowActionStickMask)
525
data[i++] = Atoms::winActionStick;
526
if (actions & CompWindowActionMinimizeMask)
527
data[i++] = Atoms::winActionMinimize;
528
if (actions & CompWindowActionMaximizeHorzMask)
529
data[i++] = Atoms::winActionMaximizeHorz;
530
if (actions & CompWindowActionMaximizeVertMask)
531
data[i++] = Atoms::winActionMaximizeVert;
532
if (actions & CompWindowActionFullscreenMask)
533
data[i++] = Atoms::winActionFullscreen;
534
if (actions & CompWindowActionCloseMask)
535
data[i++] = Atoms::winActionClose;
536
if (actions & CompWindowActionShadeMask)
537
data[i++] = Atoms::winActionShade;
538
if (actions & CompWindowActionChangeDesktopMask)
539
data[i++] = Atoms::winActionChangeDesktop;
540
if (actions & CompWindowActionAboveMask)
541
data[i++] = Atoms::winActionAbove;
542
if (actions & CompWindowActionBelowMask)
543
data[i++] = Atoms::winActionBelow;
545
XChangeProperty (s->dpy (), id, Atoms::wmAllowedActions,
546
XA_ATOM, 32, PropModeReplace,
547
(unsigned char *) data, i);
551
CompWindow::recalcActions ()
553
unsigned int actions = 0;
554
unsigned int setActions, clearActions;
556
switch (priv->type) {
557
case CompWindowTypeFullscreenMask:
558
case CompWindowTypeNormalMask:
560
CompWindowActionMaximizeHorzMask |
561
CompWindowActionMaximizeVertMask |
562
CompWindowActionFullscreenMask |
563
CompWindowActionMoveMask |
564
CompWindowActionResizeMask |
565
CompWindowActionStickMask |
566
CompWindowActionMinimizeMask |
567
CompWindowActionCloseMask |
568
CompWindowActionChangeDesktopMask;
570
case CompWindowTypeUtilMask:
571
case CompWindowTypeMenuMask:
572
case CompWindowTypeToolbarMask:
574
CompWindowActionMoveMask |
575
CompWindowActionResizeMask |
576
CompWindowActionStickMask |
577
CompWindowActionCloseMask |
578
CompWindowActionChangeDesktopMask;
580
case CompWindowTypeDialogMask:
581
case CompWindowTypeModalDialogMask:
583
CompWindowActionMaximizeHorzMask |
584
CompWindowActionMaximizeVertMask |
585
CompWindowActionMoveMask |
586
CompWindowActionResizeMask |
587
CompWindowActionStickMask |
588
CompWindowActionCloseMask |
589
CompWindowActionChangeDesktopMask;
591
/* allow minimization for dialog windows if they
592
a) are not a transient (transients can be minimized
594
b) don't have the skip taskbar hint set (as those
595
have no target to be minimized to)
597
if (!priv->transientFor &&
598
!(priv->state & CompWindowStateSkipTaskbarMask))
600
actions |= CompWindowActionMinimizeMask;
607
actions |= CompWindowActionShadeMask;
609
actions |= (CompWindowActionAboveMask | CompWindowActionBelowMask);
611
switch (priv->wmType) {
612
case CompWindowTypeNormalMask:
613
actions |= CompWindowActionFullscreenMask |
614
CompWindowActionMinimizeMask;
619
if (priv->sizeHints.min_width == priv->sizeHints.max_width &&
620
priv->sizeHints.min_height == priv->sizeHints.max_height)
621
actions &= ~(CompWindowActionResizeMask |
622
CompWindowActionMaximizeHorzMask |
623
CompWindowActionMaximizeVertMask |
624
CompWindowActionFullscreenMask);
626
if (!(priv->mwmFunc & MwmFuncAll))
628
if (!(priv->mwmFunc & MwmFuncResize))
629
actions &= ~(CompWindowActionResizeMask |
630
CompWindowActionMaximizeHorzMask |
631
CompWindowActionMaximizeVertMask |
632
CompWindowActionFullscreenMask);
634
if (!(priv->mwmFunc & MwmFuncMove))
635
actions &= ~(CompWindowActionMoveMask |
636
CompWindowActionMaximizeHorzMask |
637
CompWindowActionMaximizeVertMask |
638
CompWindowActionFullscreenMask);
640
if (!(priv->mwmFunc & MwmFuncIconify))
641
actions &= ~CompWindowActionMinimizeMask;
643
if (!(priv->mwmFunc & MwmFuncClose))
644
actions &= ~CompWindowActionCloseMask;
647
getAllowedActions (setActions, clearActions);
648
actions &= ~clearActions;
649
actions |= setActions;
651
if (actions != priv->actions)
653
priv->actions = actions;
654
setWindowActions (screen, actions, priv->id);
659
CompWindow::getAllowedActions (unsigned int &setActions,
660
unsigned int &clearActions)
662
WRAPABLE_HND_FUNC (1, getAllowedActions, setActions, clearActions)
669
CompWindow::constrainWindowState (unsigned int state,
670
unsigned int actions)
672
if (!(actions & CompWindowActionMaximizeHorzMask))
673
state &= ~CompWindowStateMaximizedHorzMask;
675
if (!(actions & CompWindowActionMaximizeVertMask))
676
state &= ~CompWindowStateMaximizedVertMask;
678
if (!(actions & CompWindowActionShadeMask))
679
state &= ~CompWindowStateShadedMask;
681
if (!(actions & CompWindowActionFullscreenMask))
682
state &= ~CompWindowStateFullscreenMask;
688
PrivateWindow::windowTypeFromString (const char *str)
690
if (strcasecmp (str, "desktop") == 0)
691
return CompWindowTypeDesktopMask;
692
else if (strcasecmp (str, "dock") == 0)
693
return CompWindowTypeDockMask;
694
else if (strcasecmp (str, "toolbar") == 0)
695
return CompWindowTypeToolbarMask;
696
else if (strcasecmp (str, "menu") == 0)
697
return CompWindowTypeMenuMask;
698
else if (strcasecmp (str, "utility") == 0)
699
return CompWindowTypeUtilMask;
700
else if (strcasecmp (str, "splash") == 0)
701
return CompWindowTypeSplashMask;
702
else if (strcasecmp (str, "dialog") == 0)
703
return CompWindowTypeDialogMask;
704
else if (strcasecmp (str, "normal") == 0)
705
return CompWindowTypeNormalMask;
706
else if (strcasecmp (str, "dropdownmenu") == 0)
707
return CompWindowTypeDropdownMenuMask;
708
else if (strcasecmp (str, "popupmenu") == 0)
709
return CompWindowTypePopupMenuMask;
710
else if (strcasecmp (str, "tooltip") == 0)
711
return CompWindowTypeTooltipMask;
712
else if (strcasecmp (str, "notification") == 0)
713
return CompWindowTypeNotificationMask;
714
else if (strcasecmp (str, "combo") == 0)
715
return CompWindowTypeComboMask;
716
else if (strcasecmp (str, "dnd") == 0)
717
return CompWindowTypeDndMask;
718
else if (strcasecmp (str, "modaldialog") == 0)
719
return CompWindowTypeModalDialogMask;
720
else if (strcasecmp (str, "fullscreen") == 0)
721
return CompWindowTypeFullscreenMask;
722
else if (strcasecmp (str, "unknown") == 0)
723
return CompWindowTypeUnknownMask;
724
else if (strcasecmp (str, "any") == 0)
731
CompWindow::recalcType ()
737
if (!overrideRedirect () && priv->wmType == CompWindowTypeUnknownMask)
738
type = CompWindowTypeNormalMask;
740
if (priv->state & CompWindowStateFullscreenMask)
741
type = CompWindowTypeFullscreenMask;
743
if (type == CompWindowTypeNormalMask)
745
if (priv->transientFor)
746
type = CompWindowTypeDialogMask;
749
if (type == CompWindowTypeDockMask &&
750
(priv->state & CompWindowStateBelowMask))
752
type = CompWindowTypeNormalMask;
755
if ((type & (CompWindowTypeNormalMask | CompWindowTypeDialogMask)) &&
756
(priv->state & CompWindowStateModalMask))
758
type = CompWindowTypeModalDialogMask;
766
PrivateWindow::updateFrameWindow ()
771
if (input.left || input.right || input.top || input.bottom)
773
int x, y, width, height;
774
int bw = serverGeometry.border () * 2;
776
x = serverGeometry.x () - input.left;
777
y = serverGeometry.y () - input.top;
778
width = serverGeometry.width () + input.left + input.right + bw;
779
height = serverGeometry.height () + input.top + input.bottom + bw;
782
height = input.top + input.bottom;
784
XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
787
XUnmapWindow (screen->dpy (), wrapper);
791
XMapWindow (screen->dpy (), wrapper);
792
XMoveResizeWindow (screen->dpy (), wrapper, input.left, input.top,
793
serverGeometry.width (), serverGeometry.height ());
795
XMoveResizeWindow (screen->dpy (), id, 0, 0,
796
serverGeometry.width (), serverGeometry.height ());
797
window->sendConfigureNotify ();
799
window->updateFrameRegion ();
800
window->windowNotify (CompWindowNotifyFrameUpdate);
804
int x, y, width, height;
805
int bw = serverGeometry.border () * 2;
807
x = serverGeometry.x ();
808
y = serverGeometry.y ();
809
width = serverGeometry.width () + bw;
810
height = serverGeometry.height () + bw;
815
XMoveResizeWindow (screen->dpy (), frame, x, y, width, height);
818
XUnmapWindow (screen->dpy (), wrapper);
822
XMapWindow (screen->dpy (), wrapper);
823
XMoveResizeWindow (screen->dpy (), wrapper, 0, 0,
824
serverGeometry.width (), serverGeometry.height ());
826
XMoveResizeWindow (screen->dpy (), id, 0, 0,
827
serverGeometry.width (), serverGeometry.height ());
828
window->sendConfigureNotify ();
829
frameRegion = CompRegion ();
830
window->windowNotify (CompWindowNotifyFrameUpdate);
833
window->recalcActions ();
839
CompWindow::updateWindowOutputExtents ()
841
CompWindowExtents output (priv->output);
843
getOutputExtents (output);
845
if (output.left != priv->output.left ||
846
output.right != priv->output.right ||
847
output.top != priv->output.top ||
848
output.bottom != priv->output.bottom)
850
priv->output = output;
852
resizeNotify (0, 0, 0, 0);
857
CompWindow::getOutputExtents (CompWindowExtents& output)
859
WRAPABLE_HND_FUNC (0, getOutputExtents, output)
868
PrivateWindow::rectsToRegion (unsigned int n, XRectangle *rects)
873
for (unsigned int i = 0; i < n; i++)
875
x1 = rects[i].x + priv->attrib.border_width;
876
y1 = rects[i].y + priv->attrib.border_width;
877
x2 = x1 + rects[i].width;
878
y2 = y1 + rects[i].height;
884
if (x2 > priv->width)
886
if (y2 > priv->height)
889
if (y1 < y2 && x1 < x2)
891
x1 += priv->attrib.x;
892
y1 += priv->attrib.y;
893
x2 += priv->attrib.x;
894
y2 += priv->attrib.y;
896
ret += CompRect (x1, y1, x2 - x1, y2 - y1);
903
/* TODO: This function should be able to check the XShape event
904
* kind and only get/set shape rectangles for either ShapeInput
905
* or ShapeBounding, but not both at the same time
909
PrivateWindow::updateRegion ()
911
XRectangle r, *boundingShapeRects = NULL;
912
XRectangle *inputShapeRects = NULL;
913
int nBounding = 0, nInput = 0;
915
priv->region = CompRegion ();
916
priv->inputRegion = CompRegion ();
918
if (screen->XShape ())
922
boundingShapeRects = XShapeGetRectangles (screen->dpy (), priv->id,
923
ShapeBounding, &nBounding, &order);
924
inputShapeRects = XShapeGetRectangles (screen->dpy (), priv->id,
925
ShapeInput, &nInput, &order);
929
r.x = -priv->attrib.border_width;
930
r.y = -priv->attrib.border_width;
931
r.width = priv->width + priv->attrib.border_width;
932
r.height = priv->height + priv->attrib.border_width;
936
boundingShapeRects = &r;
942
inputShapeRects = &r;
946
priv->region += rectsToRegion (nBounding, boundingShapeRects);
947
priv->inputRegion += rectsToRegion (nInput, inputShapeRects);
949
if (boundingShapeRects && boundingShapeRects != &r)
950
XFree (boundingShapeRects);
951
if (inputShapeRects && inputShapeRects != &r)
952
XFree (inputShapeRects);
954
window->updateFrameRegion ();
958
CompWindow::updateStruts ()
962
unsigned long n, left;
965
CompStruts oldStrut, newStrut;
971
oldStrut.left = priv->struts->left;
972
oldStrut.right = priv->struts->right;
973
oldStrut.top = priv->struts->top;
974
oldStrut.bottom = priv->struts->bottom;
985
newStrut.left.width = 0;
986
newStrut.left.height = screen->height ();
988
newStrut.right.x = screen->width ();
989
newStrut.right.y = 0;
990
newStrut.right.width = 0;
991
newStrut.right.height = screen->height ();
995
newStrut.top.width = screen->width ();
996
newStrut.top.height = 0;
998
newStrut.bottom.x = 0;
999
newStrut.bottom.y = screen->height ();
1000
newStrut.bottom.width = screen->width ();
1001
newStrut.bottom.height = 0;
1003
result = XGetWindowProperty (screen->dpy (), priv->id,
1004
Atoms::wmStrutPartial,
1005
0L, 12L, false, XA_CARDINAL, &actual, &format,
1008
if (result == Success && data)
1010
unsigned long *struts = (unsigned long *) data;
1016
newStrut.left.y = struts[4];
1017
newStrut.left.width = struts[0];
1018
newStrut.left.height = struts[5] - newStrut.left.y + 1;
1020
newStrut.right.width = struts[1];
1021
newStrut.right.x = screen->width () - newStrut.right.width;
1022
newStrut.right.y = struts[6];
1023
newStrut.right.height = struts[7] - newStrut.right.y + 1;
1025
newStrut.top.x = struts[8];
1026
newStrut.top.width = struts[9] - newStrut.top.x + 1;
1027
newStrut.top.height = struts[2];
1029
newStrut.bottom.x = struts[10];
1030
newStrut.bottom.width = struts[11] - newStrut.bottom.x + 1;
1031
newStrut.bottom.height = struts[3];
1032
newStrut.bottom.y = screen->height () - newStrut.bottom.height;
1040
result = XGetWindowProperty (screen->dpy (), priv->id,
1042
0L, 4L, false, XA_CARDINAL,
1043
&actual, &format, &n, &left, &data);
1045
if (result == Success && data)
1047
unsigned long *struts = (unsigned long *) data;
1053
newStrut.left.x = 0;
1054
newStrut.left.width = struts[0];
1056
newStrut.right.width = struts[1];
1057
newStrut.right.x = screen->width () - newStrut.right.width;
1060
newStrut.top.height = struts[2];
1062
newStrut.bottom.height = struts[3];
1063
newStrut.bottom.y = screen->height () - newStrut.bottom.height;
1072
int strutX1, strutY1, strutX2, strutY2;
1075
/* applications expect us to clip struts to xinerama edges */
1076
for (unsigned int i = 0;
1077
i < screen->screenInfo ().size (); i++)
1079
x1 = screen->screenInfo ()[i].x_org;
1080
y1 = screen->screenInfo ()[i].y_org;
1081
x2 = x1 + screen->screenInfo ()[i].width;
1082
y2 = y1 + screen->screenInfo ()[i].height;
1084
strutX1 = newStrut.left.x;
1085
strutX2 = strutX1 + newStrut.left.width;
1086
strutY1 = newStrut.left.y;
1087
strutY2 = strutY1 + newStrut.left.height;
1089
if (strutX2 > x1 && strutX2 <= x2 &&
1090
strutY1 < y2 && strutY2 > y1)
1092
newStrut.left.x = x1;
1093
newStrut.left.width = strutX2 - x1;
1096
strutX1 = newStrut.right.x;
1097
strutX2 = strutX1 + newStrut.right.width;
1098
strutY1 = newStrut.right.y;
1099
strutY2 = strutY1 + newStrut.right.height;
1101
if (strutX1 > x1 && strutX1 <= x2 &&
1102
strutY1 < y2 && strutY2 > y1)
1104
newStrut.right.x = strutX1;
1105
newStrut.right.width = x2 - strutX1;
1108
strutX1 = newStrut.top.x;
1109
strutX2 = strutX1 + newStrut.top.width;
1110
strutY1 = newStrut.top.y;
1111
strutY2 = strutY1 + newStrut.top.height;
1113
if (strutX1 < x2 && strutX2 > x1 &&
1114
strutY2 > y1 && strutY2 <= y2)
1116
newStrut.top.y = y1;
1117
newStrut.top.height = strutY2 - y1;
1120
strutX1 = newStrut.bottom.x;
1121
strutX2 = strutX1 + newStrut.bottom.width;
1122
strutY1 = newStrut.bottom.y;
1123
strutY2 = strutY1 + newStrut.bottom.height;
1125
if (strutX1 < x2 && strutX2 > x1 &&
1126
strutY1 > y1 && strutY1 <= y2)
1128
newStrut.bottom.y = strutY1;
1129
newStrut.bottom.height = y2 - strutY1;
1134
if (hasOld != hasNew ||
1135
(hasNew && hasOld &&
1136
memcmp (&newStrut, &oldStrut, sizeof (CompStruts))))
1142
priv->struts = (CompStruts *) malloc (sizeof (CompStruts));
1147
*priv->struts = newStrut;
1151
free (priv->struts);
1152
priv->struts = NULL;
1162
CompWindow::incrementDestroyReference ()
1164
priv->destroyRefCnt++;
1168
CompWindow::destroy ()
1170
windowNotify (CompWindowNotifyBeforeDestroy);
1172
screen->priv->eraseWindowFromMap (id ());
1177
priv->destroyRefCnt--;
1178
if (priv->destroyRefCnt)
1182
if (!priv->destroyed)
1184
priv->destroyed = true;
1185
screen->priv->pendingDestroys++;
1189
priv->unreparent ();
1194
CompWindow::sendConfigureNotify ()
1196
XConfigureEvent xev;
1198
xev.type = ConfigureNotify;
1199
xev.event = priv->id;
1200
xev.window = priv->id;
1202
/* normally we should never send configure notify events to override
1203
redirect windows but if they support the _NET_WM_SYNC_REQUEST
1204
protocol we need to do this when the window is mapped. however the
1205
only way we can make sure that the attributes we send are correct
1206
and is to grab the server. */
1207
if (priv->attrib.override_redirect)
1209
XWindowAttributes attrib;
1211
XGrabServer (screen->dpy ());
1213
if (XGetWindowAttributes (screen->dpy (), priv->id, &attrib))
1217
xev.width = attrib.width;
1218
xev.height = attrib.height;
1219
xev.border_width = attrib.border_width;
1221
xev.above = (prev) ? prev->priv->id : None;
1222
xev.override_redirect = true;
1224
XSendEvent (screen->dpy (), priv->id, false,
1225
StructureNotifyMask, (XEvent *) &xev);
1228
XUngrabServer (screen->dpy ());
1229
XSync (screen->dpy (), false);
1233
xev.x = priv->serverGeometry.x ();
1234
xev.y = priv->serverGeometry.y ();
1235
xev.width = priv->serverGeometry.width ();
1236
xev.height = priv->serverGeometry.height ();
1237
xev.border_width = priv->serverGeometry.border ();
1239
xev.above = (prev) ? prev->priv->id : None;
1240
xev.override_redirect = priv->attrib.override_redirect;
1242
XSendEvent (screen->dpy (), priv->id, false,
1243
StructureNotifyMask, (XEvent *) &xev);
1250
windowNotify (CompWindowNotifyBeforeMap);
1254
if (priv->pendingMaps > 0)
1255
priv->pendingMaps = 0;
1257
priv->mapNum = screen->priv->mapNum++;
1260
screen->updateWorkarea ();
1262
if (windowClass () == InputOnly)
1265
priv->unmapRefCnt = 1;
1267
priv->attrib.map_state = IsViewable;
1269
if (!overrideRedirect ())
1270
screen->priv->setWmState (NormalState, priv->id);
1272
priv->invisible = true;
1275
priv->lastPong = screen->priv->lastPing;
1277
priv->updateRegion ();
1278
priv->updateSize ();
1280
screen->priv->updateClientList ();
1282
if (priv->type & CompWindowTypeDesktopMask)
1283
screen->priv->desktopWindowCount++;
1285
if (priv->protocols & CompWindowProtocolSyncRequestMask)
1288
sendConfigureNotify ();
1291
if (!overrideRedirect ())
1295
resize (priv->attrib.x, priv->attrib.y, priv->attrib.width,
1296
++priv->attrib.height - 1, priv->attrib.border_width);
1300
windowNotify (CompWindowNotifyMap);
1304
CompWindow::incrementUnmapReference ()
1306
priv->unmapRefCnt++;
1310
CompWindow::unmap ()
1312
windowNotify (CompWindowNotifyBeforeUnmap);
1317
priv->unmapRefCnt--;
1318
if (priv->unmapRefCnt > 0)
1321
if (priv->unmanaging)
1325
int gravity = priv->sizeHints.win_gravity;
1328
priv->unreparent ();
1330
/* revert gravity adjustment made at MapNotify time */
1331
xwc.x = priv->serverGeometry.x ();
1332
xwc.y = priv->serverGeometry.y ();
1336
xwcm = priv->adjustConfigureRequestForGravity (&xwc,
1341
configureXWindow (xwcm, &xwc);
1343
priv->unmanaging = false;
1347
screen->updateWorkarea ();
1349
if (priv->attrib.map_state != IsViewable)
1352
if (priv->type == CompWindowTypeDesktopMask)
1353
screen->priv->desktopWindowCount--;
1355
priv->attrib.map_state = IsUnmapped;
1357
priv->invisible = true;
1359
if (priv->shaded && priv->height)
1360
resize (priv->attrib.x, priv->attrib.y,
1361
priv->attrib.width, ++priv->attrib.height - 1,
1362
priv->attrib.border_width);
1364
screen->priv->updateClientList ();
1366
windowNotify (CompWindowNotifyUnmap);
1370
PrivateWindow::withdraw ()
1372
if (!attrib.override_redirect)
1373
screen->priv->setWmState (WithdrawnState, id);
1376
unmanaging = managed;
1381
PrivateWindow::restack (Window aboveId)
1383
if (aboveId && (aboveId == id || aboveId == frame))
1384
// Don't try to raise a window above itself
1386
else if (window->prev)
1388
if (aboveId && (aboveId == window->prev->id () ||
1389
aboveId == window->prev->frame ()))
1392
else if (aboveId == None && !window->next)
1395
if (aboveId && !screen->findTopLevelWindow (aboveId, true))
1398
screen->unhookWindow (window);
1399
screen->insertWindow (window, aboveId);
1401
screen->priv->updateClientList ();
1403
window->windowNotify (CompWindowNotifyRestack);
1409
CompWindow::resize (XWindowAttributes attr)
1411
return resize (Geometry (attr.x, attr.y, attr.width, attr.height,
1412
attr.border_width));
1416
CompWindow::resize (int x,
1422
return resize (Geometry (x, y, width, height, border));
1426
CompWindow::resize (CompWindow::Geometry gm)
1428
if (priv->attrib.width != gm.width () ||
1429
priv->attrib.height != gm.height () ||
1430
priv->attrib.border_width != gm.border ())
1433
int dx, dy, dwidth, dheight;
1435
pw = gm.width () + gm.border () * 2;
1436
ph = gm.height () + gm.border () * 2;
1441
dx = gm.x () - priv->attrib.x;
1442
dy = gm.y () - priv->attrib.y;
1443
dwidth = gm.width () - priv->attrib.width;
1444
dheight = gm.height () - priv->attrib.height;
1446
priv->attrib.x = gm.x ();
1447
priv->attrib.y = gm.y ();
1448
priv->attrib.width = gm.width ();
1449
priv->attrib.height = gm.height ();
1450
priv->attrib.border_width = gm.border ();
1452
priv->geometry.set (priv->attrib.x, priv->attrib.y,
1453
priv->attrib.width, priv->attrib.height,
1454
priv->attrib.border_width);
1460
priv->updateRegion ();
1462
resizeNotify (dx, dy, dwidth, dheight);
1464
priv->invisible = WINDOW_INVISIBLE (priv);
1465
priv->updateFrameWindow ();
1467
else if (priv->attrib.x != gm.x () || priv->attrib.y != gm.y ())
1471
dx = gm.x () - priv->attrib.x;
1472
dy = gm.y () - priv->attrib.y;
1481
syncValueIncrement (XSyncValue *value)
1486
XSyncIntToValue (&one, 1);
1487
XSyncValueAdd (value, *value, one, &overflow);
1491
PrivateWindow::initializeSyncCounter ()
1493
XSyncAlarmAttributes values;
1496
unsigned long n, left;
1497
unsigned char *data;
1500
return syncAlarm != None;
1502
if (!(protocols & CompWindowProtocolSyncRequestMask))
1505
result = XGetWindowProperty (screen->dpy (), id,
1506
Atoms::wmSyncRequestCounter,
1507
0L, 1L, false, XA_CARDINAL, &actual, &format,
1510
if (result == Success && n && data)
1512
unsigned long *counter = (unsigned long *) data;
1514
syncCounter = *counter;
1518
XSyncIntsToValue (&syncValue, (unsigned int) rand (), 0);
1519
XSyncSetCounter (screen->dpy (),
1523
syncValueIncrement (&syncValue);
1525
values.events = true;
1527
values.trigger.counter = syncCounter;
1528
values.trigger.wait_value = syncValue;
1530
values.trigger.value_type = XSyncAbsolute;
1531
values.trigger.test_type = XSyncPositiveComparison;
1533
XSyncIntToValue (&values.delta, 1);
1535
values.events = true;
1537
CompScreen::checkForError (screen->dpy ());
1539
/* Note that by default, the alarm increments the trigger value
1540
* when it fires until the condition (counter.value < trigger.value)
1543
syncAlarm = XSyncCreateAlarm (screen->dpy (),
1552
if (CompScreen::checkForError (screen->dpy ()))
1555
XSyncDestroyAlarm (screen->dpy (), syncAlarm);
1558
else if (result == Success && data)
1567
CompWindow::sendSyncRequest ()
1569
XClientMessageEvent xev;
1574
if (!priv->initializeSyncCounter ())
1577
xev.type = ClientMessage;
1578
xev.window = priv->id;
1579
xev.message_type = Atoms::wmProtocols;
1581
xev.data.l[0] = Atoms::wmSyncRequest;
1582
xev.data.l[1] = CurrentTime;
1583
xev.data.l[2] = XSyncValueLow32 (priv->syncValue);
1584
xev.data.l[3] = XSyncValueHigh32 (priv->syncValue);
1587
syncValueIncrement (&priv->syncValue);
1589
XSendEvent (screen->dpy (), priv->id, false, 0, (XEvent *) &xev);
1591
priv->syncWait = true;
1592
priv->syncGeometry = priv->serverGeometry;
1594
if (!priv->syncWaitTimer.active ())
1595
priv->syncWaitTimer.start ();
1599
PrivateWindow::configure (XConfigureEvent *ce)
1604
priv->attrib.override_redirect = ce->override_redirect;
1608
priv->syncGeometry.set (ce->x, ce->y, ce->width, ce->height,
1613
if (ce->override_redirect)
1615
priv->serverGeometry.set (ce->x, ce->y, ce->width, ce->height,
1619
window->resize (ce->x, ce->y, ce->width, ce->height, ce->border_width);
1622
if (ce->event == screen->root ())
1623
priv->restack (ce->above);
1627
PrivateWindow::configureFrame (XConfigureEvent *ce)
1629
int x, y, width, height;
1635
x = ce->x + priv->input.left;
1636
y = ce->y + priv->input.top;
1637
width = ce->width - priv->serverGeometry.border () * 2 - priv->input.left - priv->input.right;
1638
height = ce->height - priv->serverGeometry.border () * 2 - priv->input.top - priv->input.bottom;
1642
priv->syncGeometry.set (x, y, width, height, ce->border_width);
1646
if (ce->override_redirect)
1648
priv->serverGeometry.set (x, y, width, height, ce->border_width);
1651
window->resize (x, y, width, height, ce->border_width);
1654
if (priv->restack (ce->above))
1655
priv->updatePassiveButtonGrabs ();
1657
above = screen->findWindow (ce->above);
1660
above->priv->updatePassiveButtonGrabs ();
1664
PrivateWindow::circulate (XCirculateEvent *ce)
1668
if (ce->place == PlaceOnTop)
1669
newAboveId = screen->priv->getTopWindow ();
1673
priv->restack (newAboveId);
1677
CompWindow::move (int dx,
1683
priv->attrib.x += dx;
1684
priv->attrib.y += dy;
1686
priv->geometry.setX (priv->attrib.x);
1687
priv->geometry.setY (priv->attrib.y);
1689
priv->region.translate (dx, dy);
1690
priv->inputRegion.translate (dx, dy);
1691
if (!priv->frameRegion.isEmpty ())
1692
priv->frameRegion.translate (dx, dy);
1694
priv->invisible = WINDOW_INVISIBLE (priv);
1696
moveNotify (dx, dy, immediate);
1701
CompWindow::syncPosition ()
1703
priv->serverGeometry.setX (priv->attrib.x);
1704
priv->serverGeometry.setY (priv->attrib.y);
1706
XMoveWindow (screen->dpy (), ROOTPARENT (this),
1707
priv->attrib.x - priv->input.left,
1708
priv->attrib.y - priv->input.top);
1712
XMoveWindow (screen->dpy (), priv->wrapper,
1713
priv->input.left, priv->input.top);
1714
sendConfigureNotify ();
1719
CompWindow::focus ()
1721
WRAPABLE_HND_FUNC_RETURN (2, bool, focus)
1723
if (overrideRedirect ())
1726
if (!priv->managed || priv->unmanaging)
1729
if (!onCurrentDesktop ())
1732
if (priv->destroyed)
1735
if (!priv->shaded && (priv->state & CompWindowStateHiddenMask))
1738
if (priv->attrib.x + priv->width <= 0 ||
1739
priv->attrib.y + priv->height <= 0 ||
1740
priv->attrib.x >= (int) screen->width ()||
1741
priv->attrib.y >= (int) screen->height ())
1748
CompWindow::place (CompPoint &pos)
1750
WRAPABLE_HND_FUNC_RETURN (4, bool, place, pos)
1755
CompWindow::validateResizeRequest (unsigned int &mask,
1756
XWindowChanges *xwc,
1757
unsigned int source)
1759
WRAPABLE_HND_FUNC (5, validateResizeRequest, mask, xwc, source)
1761
if (!(priv->type & (CompWindowTypeDockMask |
1762
CompWindowTypeFullscreenMask |
1763
CompWindowTypeUnknownMask)))
1769
min = screen->workArea ().y () + priv->input.top;
1770
max = screen->workArea ().bottom ();
1772
if (priv->state & CompWindowStateStickyMask &&
1773
(xwc->y < min || xwc->y > max))
1775
xwc->y = priv->serverGeometry.y ();
1779
min -= screen->vp ().y () * screen->height ();
1780
max += (screen->vpSize ().height () - screen->vp ().y () - 1) *
1785
else if (xwc->y > max)
1794
min = screen->workArea ().x () + priv->input.left;
1795
max = screen->workArea ().right ();
1797
if (priv->state & CompWindowStateStickyMask &&
1798
(xwc->x < min || xwc->x > max))
1800
xwc->x = priv->serverGeometry.x ();
1804
min -= screen->vp ().x () * screen->width ();
1805
max += (screen->vpSize ().width () - screen->vp ().x () - 1) *
1810
else if (xwc->x > max)
1818
CompWindow::resizeNotify (int dx,
1822
WRAPABLE_HND_FUNC (6, resizeNotify, dx, dy, dwidth, dheight)
1825
CompWindow::moveNotify (int dx,
1828
WRAPABLE_HND_FUNC (7, moveNotify, dx, dy, immediate)
1831
CompWindow::windowNotify (CompWindowNotify n)
1832
WRAPABLE_HND_FUNC (8, windowNotify, n)
1835
CompWindow::grabNotify (int x,
1840
WRAPABLE_HND_FUNC (9, grabNotify, x, y, state, mask)
1841
priv->grabbed = true;
1845
CompWindow::ungrabNotify ()
1847
WRAPABLE_HND_FUNC (10, ungrabNotify)
1848
priv->grabbed = false;
1852
CompWindow::stateChangeNotify (unsigned int lastState)
1854
WRAPABLE_HND_FUNC (11, stateChangeNotify, lastState);
1856
/* if being made sticky */
1857
if (!(lastState & CompWindowStateStickyMask) &&
1858
(priv->state & CompWindowStateStickyMask))
1860
CompPoint vp; /* index of the window's vp */
1862
/* Find which viewport the window falls in,
1863
and check if it's the current viewport */
1864
vp = defaultViewport ();
1865
if (screen->vp () != vp)
1867
int moveX = (screen->vp ().x () - vp.x ()) * screen->width ();
1868
int moveY = (screen->vp ().y () - vp.y ()) * screen->height ();
1870
move (moveX, moveY, TRUE);
1878
PrivateWindow::isGroupTransient (Window clientLeader)
1883
if (transientFor == None || transientFor == screen->root ())
1885
if (type & (CompWindowTypeUtilMask |
1886
CompWindowTypeToolbarMask |
1887
CompWindowTypeMenuMask |
1888
CompWindowTypeDialogMask |
1889
CompWindowTypeModalDialogMask))
1891
if (this->clientLeader == clientLeader)
1900
PrivateWindow::getModalTransient ()
1902
CompWindow *w, *modalTransient;
1904
modalTransient = window;
1906
for (w = screen->windows ().back (); w; w = w->prev)
1908
if (w == modalTransient || w->priv->mapNum == 0)
1911
if (w->priv->transientFor == modalTransient->priv->id)
1913
if (w->priv->state & CompWindowStateModalMask)
1916
w = screen->windows ().back ();
1921
if (modalTransient == window)
1923
/* don't look for group transients with modal state if current window
1925
if (state & CompWindowStateModalMask)
1928
for (w = screen->windows ().back (); w; w = w->prev)
1930
if (w == modalTransient || w->priv->mapNum == 0)
1933
if (isAncestorTo (modalTransient, w))
1936
if (w->priv->isGroupTransient (modalTransient->priv->clientLeader))
1938
if (w->priv->state & CompWindowStateModalMask)
1941
w = w->priv->getModalTransient ();
1951
if (modalTransient == window)
1952
modalTransient = NULL;
1954
return modalTransient;
1958
CompWindow::moveInputFocusTo ()
1960
CompScreen *s = screen;
1961
CompWindow *modalTransient;
1963
modalTransient = priv->getModalTransient ();
1965
return modalTransient->moveInputFocusTo ();
1967
if (priv->state & CompWindowStateHiddenMask)
1969
XSetInputFocus (s->dpy (), priv->frame,
1970
RevertToPointerRoot, CurrentTime);
1971
XChangeProperty (s->dpy (), s->root (), Atoms::winActive,
1972
XA_WINDOW, 32, PropModeReplace,
1973
(unsigned char *) &priv->id, 1);
1977
bool setFocus = false;
1979
if (priv->inputHint)
1981
XSetInputFocus (s->dpy (), priv->id, RevertToPointerRoot,
1986
if (priv->protocols & CompWindowProtocolTakeFocusMask)
1990
ev.type = ClientMessage;
1991
ev.xclient.window = priv->id;
1992
ev.xclient.message_type = Atoms::wmProtocols;
1993
ev.xclient.format = 32;
1994
ev.xclient.data.l[0] = Atoms::wmTakeFocus;
1995
ev.xclient.data.l[1] = s->getCurrentTime ();
1996
ev.xclient.data.l[2] = 0;
1997
ev.xclient.data.l[3] = 0;
1998
ev.xclient.data.l[4] = 0;
2000
XSendEvent (s->dpy (), priv->id, false, NoEventMask, &ev);
2006
screen->priv->nextActiveWindow = priv->id;
2008
if (!setFocus && !modalTransient)
2010
CompWindow *ancestor;
2012
/* move input to closest ancestor */
2013
for (ancestor = s->windows ().front (); ancestor;
2014
ancestor = ancestor->next)
2016
if (PrivateWindow::isAncestorTo (this, ancestor))
2018
ancestor->moveInputFocusTo ();
2027
CompWindow::moveInputFocusToOtherWindow ()
2029
if (priv->id == screen->activeWindow () ||
2030
priv->id == screen->priv->nextActiveWindow)
2032
CompWindow *ancestor;
2034
if (priv->transientFor && priv->transientFor != screen->root ())
2036
ancestor = screen->findWindow (priv->transientFor);
2038
ancestor->focus () &&
2039
!(ancestor->priv->type & (CompWindowTypeDesktopMask |
2040
CompWindowTypeDockMask)))
2042
ancestor->moveInputFocusTo ();
2045
screen->focusDefaultWindow ();
2047
else if (priv->type & (CompWindowTypeDialogMask |
2048
CompWindowTypeModalDialogMask))
2050
CompWindow *a, *focus = NULL;
2052
for (a = screen->windows ().back (); a; a = a->prev)
2054
if (a->priv->clientLeader == priv->clientLeader)
2060
if (a->priv->type & (CompWindowTypeNormalMask |
2061
CompWindowTypeDialogMask |
2062
CompWindowTypeModalDialogMask))
2064
if (priv->compareWindowActiveness (focus, a) < 0)
2074
if (focus && !(focus->priv->type & (CompWindowTypeDesktopMask |
2075
CompWindowTypeDockMask)))
2077
focus->moveInputFocusTo ();
2080
screen->focusDefaultWindow ();
2083
screen->focusDefaultWindow ();
2089
PrivateWindow::stackLayerCheck (CompWindow *w,
2090
Window clientLeader,
2093
if (isAncestorTo (w, below))
2096
if (isAncestorTo (below, w))
2099
if (clientLeader && below->priv->clientLeader == clientLeader)
2100
if (below->priv->isGroupTransient (clientLeader))
2103
if (w->priv->state & CompWindowStateAboveMask)
2107
else if (w->priv->state & CompWindowStateBelowMask)
2109
if (below->priv->state & CompWindowStateBelowMask)
2112
else if (!(below->priv->state & CompWindowStateAboveMask))
2121
PrivateWindow::avoidStackingRelativeTo (CompWindow *w)
2123
if (w->overrideRedirect ())
2126
if (!w->priv->shaded && !w->priv->pendingMaps)
2128
if (!w->isViewable () || !w->isMapped ())
2135
/* goes through the stack, top-down until we find a window we should
2136
stack above, normal windows can be stacked above fullscreen windows
2137
(and fullscreen windows over others in their layer) if aboveFs is true. */
2139
PrivateWindow::findSiblingBelow (CompWindow *w,
2143
Window clientLeader = w->priv->clientLeader;
2144
unsigned int type = w->priv->type;
2145
unsigned int belowMask;
2148
belowMask = CompWindowTypeDockMask;
2150
belowMask = CompWindowTypeDockMask | CompWindowTypeFullscreenMask;
2152
/* normal stacking of fullscreen windows with below state */
2153
if ((type & CompWindowTypeFullscreenMask) &&
2154
(w->priv->state & CompWindowStateBelowMask))
2155
type = CompWindowTypeNormalMask;
2157
if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2158
clientLeader = None;
2160
for (below = screen->windows ().back (); below;
2161
below = below->prev)
2163
if (below == w || avoidStackingRelativeTo (below))
2166
/* always above desktop windows */
2167
if (below->priv->type & CompWindowTypeDesktopMask)
2171
case CompWindowTypeDesktopMask:
2172
/* desktop window layer */
2174
case CompWindowTypeFullscreenMask:
2177
/* otherwise fall-through */
2178
case CompWindowTypeDockMask:
2179
/* fullscreen and dock layer */
2180
if (below->priv->type & (CompWindowTypeFullscreenMask |
2181
CompWindowTypeDockMask))
2183
if (stackLayerCheck (w, clientLeader, below))
2192
/* fullscreen and normal layer */
2193
if (!(below->priv->type & belowMask))
2195
if (stackLayerCheck (w, clientLeader, below))
2205
/* goes through the stack, top-down and returns the lowest window we
2208
PrivateWindow::findLowestSiblingBelow (CompWindow *w)
2210
CompWindow *below, *lowest = screen->windows ().back ();
2211
Window clientLeader = w->priv->clientLeader;
2212
unsigned int type = w->priv->type;
2214
/* normal stacking fullscreen windows with below state */
2215
if ((type & CompWindowTypeFullscreenMask) &&
2216
(w->priv->state & CompWindowStateBelowMask))
2217
type = CompWindowTypeNormalMask;
2219
if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2220
clientLeader = None;
2222
for (below = screen->windows ().back (); below;
2223
below = below->prev)
2225
if (below == w || avoidStackingRelativeTo (below))
2228
/* always above desktop windows */
2229
if (below->priv->type & CompWindowTypeDesktopMask)
2233
case CompWindowTypeDesktopMask:
2234
/* desktop window layer - desktop windows always should be
2235
stacked at the bottom; no other window should be below them */
2238
case CompWindowTypeFullscreenMask:
2239
case CompWindowTypeDockMask:
2240
/* fullscreen and dock layer */
2241
if (below->priv->type & (CompWindowTypeFullscreenMask |
2242
CompWindowTypeDockMask))
2244
if (!stackLayerCheck (below, clientLeader, w))
2253
/* fullscreen and normal layer */
2254
if (!(below->priv->type & CompWindowTypeDockMask))
2256
if (!stackLayerCheck (below, clientLeader, w))
2269
PrivateWindow::validSiblingBelow (CompWindow *w,
2270
CompWindow *sibling)
2272
Window clientLeader = w->priv->clientLeader;
2273
unsigned int type = w->priv->type;
2275
/* normal stacking fullscreen windows with below state */
2276
if ((type & CompWindowTypeFullscreenMask) &&
2277
(w->priv->state & CompWindowStateBelowMask))
2278
type = CompWindowTypeNormalMask;
2280
if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2281
clientLeader = None;
2283
if (sibling == w || avoidStackingRelativeTo (sibling))
2286
/* always above desktop windows */
2287
if (sibling->priv->type & CompWindowTypeDesktopMask)
2291
case CompWindowTypeDesktopMask:
2292
/* desktop window layer */
2294
case CompWindowTypeFullscreenMask:
2295
case CompWindowTypeDockMask:
2296
/* fullscreen and dock layer */
2297
if (sibling->priv->type & (CompWindowTypeFullscreenMask |
2298
CompWindowTypeDockMask))
2300
if (stackLayerCheck (w, clientLeader, sibling))
2309
/* fullscreen and normal layer */
2310
if (!(sibling->priv->type & CompWindowTypeDockMask))
2312
if (stackLayerCheck (w, clientLeader, sibling))
2322
PrivateWindow::saveGeometry (int mask)
2324
int m = mask & ~saveMask;
2326
/* only save geometry if window has been placed */
2331
saveWc.x = serverGeometry.x ();
2334
saveWc.y = serverGeometry.y ();
2337
saveWc.width = serverGeometry.width ();
2340
saveWc.height = serverGeometry.height ();
2342
if (m & CWBorderWidth)
2343
saveWc.border_width = serverGeometry.border ();
2349
PrivateWindow::restoreGeometry (XWindowChanges *xwc,
2352
int m = mask & saveMask;
2362
xwc->width = saveWc.width;
2364
/* This is not perfect but it works OK for now. If the saved width is
2365
the same as the current width then make it a little be smaller so
2366
the user can see that it changed and it also makes sure that
2367
windowResizeNotify is called and plugins are notified. */
2368
if (xwc->width == (int) serverGeometry.width ())
2378
xwc->height = saveWc.height;
2380
/* As above, if the saved height is the same as the current height
2381
then make it a little be smaller. */
2382
if (xwc->height == (int) serverGeometry.height ())
2390
if (m & CWBorderWidth)
2391
xwc->border_width = saveWc.border_width;
2399
PrivateWindow::reconfigureXWindow (unsigned int valueMask,
2400
XWindowChanges *xwc)
2402
if (valueMask & CWX)
2403
serverGeometry.setX (xwc->x);
2405
if (valueMask & CWY)
2406
serverGeometry.setY (xwc->y);
2408
if (valueMask & CWWidth)
2409
serverGeometry.setWidth (xwc->width);
2411
if (valueMask & CWHeight)
2412
serverGeometry.setHeight (xwc->height);
2414
if (valueMask & CWBorderWidth)
2415
serverGeometry.setBorder (xwc->border_width);
2417
/* Compiz's window list is immediately restacked on reconfigureXWindow
2418
in order to ensure correct operation of the raise, lower and restacking
2419
functions. This function should only recieve stack_mode == Above
2420
but warn incase something else does get through, to make the cause
2421
of any potential misbehaviour obvious. */
2422
if (valueMask & (CWSibling | CWStackMode))
2424
if (xwc->stack_mode == Above)
2425
restack (xwc->sibling);
2427
compLogMessage ("core", CompLogLevelWarn, "restack_mode not Above");
2432
XWindowChanges wc = *xwc;
2434
wc.x -= input.left - serverGeometry.border ();
2435
wc.y -= input.top - serverGeometry.border ();
2436
wc.width += input.left + input.right + serverGeometry.border ();
2437
wc.height += input.top + input.bottom + serverGeometry.border ();
2439
XConfigureWindow (screen->dpy (), frame, valueMask, &wc);
2440
valueMask &= ~(CWSibling | CWStackMode);
2442
xwc->x = input.left;
2444
XConfigureWindow (screen->dpy (), wrapper, valueMask, xwc);
2450
XConfigureWindow (screen->dpy (), id, valueMask, xwc);
2454
PrivateWindow::stackTransients (CompWindow *w,
2456
XWindowChanges *xwc,
2457
CompWindowList &updateList)
2460
Window clientLeader = w->priv->clientLeader;
2462
if (w->priv->transientFor || w->priv->isGroupTransient (clientLeader))
2463
clientLeader = None;
2465
for (t = screen->windows ().back (); t; t = t->prev)
2467
if (t == w || t == avoid)
2470
if (t->priv->transientFor == w->priv->id ||
2471
t->priv->isGroupTransient (clientLeader))
2473
if (w->priv->type & CompWindowTypeDockMask)
2474
if (!(t->priv->type & CompWindowTypeDockMask))
2477
if (!stackTransients (t, avoid, xwc, updateList))
2480
if (xwc->sibling == t->priv->id ||
2481
(t->priv->frame && xwc->sibling == t->priv->frame))
2484
if (t->priv->mapNum || t->priv->pendingMaps)
2485
updateList.push_back (t);
2493
PrivateWindow::stackAncestors (CompWindow *w,
2494
XWindowChanges *xwc,
2495
CompWindowList &updateList)
2497
CompWindow *transient = NULL;
2499
if (w->priv->transientFor)
2500
transient = screen->findWindow (w->priv->transientFor);
2503
xwc->sibling != transient->priv->id &&
2504
(!transient->priv->frame || xwc->sibling != transient->priv->frame))
2506
CompWindow *ancestor;
2508
ancestor = screen->findWindow (w->priv->transientFor);
2511
if (!stackTransients (ancestor, w, xwc, updateList))
2514
if (ancestor->priv->type & CompWindowTypeDesktopMask)
2517
if (ancestor->priv->type & CompWindowTypeDockMask)
2518
if (!(w->priv->type & CompWindowTypeDockMask))
2521
if (ancestor->priv->mapNum || ancestor->priv->pendingMaps)
2522
updateList.push_back (ancestor);
2524
stackAncestors (ancestor, xwc, updateList);
2527
else if (w->priv->isGroupTransient (w->priv->clientLeader))
2531
for (a = screen->windows ().back (); a; a = a->prev)
2533
if (a->priv->clientLeader == w->priv->clientLeader &&
2534
a->priv->transientFor == None &&
2535
!a->priv->isGroupTransient (w->priv->clientLeader))
2537
if (xwc->sibling == a->priv->id ||
2538
(a->priv->frame && xwc->sibling == a->priv->frame))
2541
if (!stackTransients (a, w, xwc, updateList))
2544
if (a->priv->type & CompWindowTypeDesktopMask)
2547
if (a->priv->type & CompWindowTypeDockMask)
2548
if (!(w->priv->type & CompWindowTypeDockMask))
2551
if (a->priv->mapNum || a->priv->pendingMaps)
2552
updateList.push_back (a);
2559
CompWindow::configureXWindow (unsigned int valueMask,
2560
XWindowChanges *xwc)
2562
if (priv->managed && (valueMask & (CWSibling | CWStackMode)))
2564
CompWindowList transients;
2565
CompWindowList ancestors;
2567
/* Since the window list is being reordered in reconfigureXWindow
2568
the list of windows which need to be restacked must be stored
2569
first. The windows are stacked in the opposite order than they
2570
were previously stacked, in order that they are above xwc->sibling
2571
so that when compiz gets the ConfigureNotify event it doesn't
2572
have to restack all the windows again. */
2574
/* transient children above */
2575
if (PrivateWindow::stackTransients (this, NULL, xwc, transients))
2577
/* ancestors, siblings and sibling transients below */
2578
PrivateWindow::stackAncestors (this, xwc, ancestors);
2580
for (CompWindowList::reverse_iterator w = ancestors.rbegin ();
2581
w != ancestors.rend (); w++)
2583
(*w)->priv->reconfigureXWindow (CWSibling | CWStackMode, xwc);
2584
xwc->sibling = ROOTPARENT (*w);
2587
this->priv->reconfigureXWindow (valueMask, xwc);
2588
xwc->sibling = ROOTPARENT (this);
2590
for (CompWindowList::reverse_iterator w = transients.rbegin ();
2591
w != transients.rend (); w++)
2593
(*w)->priv->reconfigureXWindow (CWSibling | CWStackMode, xwc);
2594
xwc->sibling = ROOTPARENT (*w);
2600
priv->reconfigureXWindow (valueMask, xwc);
2605
PrivateWindow::addWindowSizeChanges (XWindowChanges *xwc,
2606
CompWindow::Geometry old)
2614
screen->viewportForGeometry (old, viewport);
2616
x = (viewport.x () - screen->vp ().x ()) * screen->width ();
2617
y = (viewport.y () - screen->vp ().y ()) * screen->height ();
2619
output = screen->outputDeviceForGeometry (old);
2620
workArea = screen->getWorkareaForOutput (output);
2622
if (type & CompWindowTypeFullscreenMask)
2624
saveGeometry (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
2626
if (fullscreenMonitorsSet)
2628
xwc->x = x + fullscreenMonitorRect.x ();
2629
xwc->y = y + fullscreenMonitorRect.y ();
2630
xwc->width = fullscreenMonitorRect.width ();
2631
xwc->height = fullscreenMonitorRect.height ();
2635
xwc->x = x + screen->outputDevs ()[output].x ();
2636
xwc->y = y + screen->outputDevs ()[output].y ();
2637
xwc->width = screen->outputDevs ()[output].width ();
2638
xwc->height = screen->outputDevs ()[output].height ();
2641
xwc->border_width = 0;
2643
mask |= CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
2647
mask |= restoreGeometry (xwc, CWBorderWidth);
2649
if (state & CompWindowStateMaximizedVertMask)
2651
saveGeometry (CWY | CWHeight);
2653
xwc->height = workArea.height () - input.top -
2654
input.bottom - old.border () * 2;
2660
mask |= restoreGeometry (xwc, CWY | CWHeight);
2663
if (state & CompWindowStateMaximizedHorzMask)
2665
saveGeometry (CWX | CWWidth);
2667
xwc->width = workArea.width () - input.left -
2668
input.right - old.border () * 2;
2674
mask |= restoreGeometry (xwc, CWX | CWWidth);
2677
/* constrain window width if smaller than minimum width */
2678
if (!(mask & CWWidth) && (int) old.width () < sizeHints.min_width)
2680
xwc->width = sizeHints.min_width;
2684
/* constrain window width if greater than maximum width */
2685
if (!(mask & CWWidth) && (int) old.width () > sizeHints.max_width)
2687
xwc->width = sizeHints.max_width;
2691
/* constrain window height if smaller than minimum height */
2692
if (!(mask & CWHeight) && (int) old.height () < sizeHints.min_height)
2694
xwc->height = sizeHints.min_height;
2698
/* constrain window height if greater than maximum height */
2699
if (!(mask & CWHeight) && (int) old.height () > sizeHints.max_height)
2701
xwc->height = sizeHints.max_height;
2705
if (mask & (CWWidth | CWHeight))
2707
int width, height, max;
2709
width = (mask & CWWidth) ? xwc->width : old.width ();
2710
height = (mask & CWHeight) ? xwc->height : old.height ();
2712
xwc->width = old.width ();
2713
xwc->height = old.height ();
2715
window->constrainNewWindowSize (width, height, &width, &height);
2717
if (width != (int) old.width ())
2725
if (height != (int) old.height ())
2728
xwc->height = height;
2733
if (state & CompWindowStateMaximizedVertMask)
2735
if (old.y () < y + workArea.y () + input.top)
2737
xwc->y = y + workArea.y () + input.top;
2742
height = xwc->height + old.border () * 2;
2744
max = y + workArea.bottom ();
2745
if (old.y () + (int) old.height () + input.bottom > max)
2747
xwc->y = max - height - input.bottom;
2750
else if (old.y () + height + input.bottom > max)
2752
xwc->y = y + workArea.y () +
2753
(workArea.height () - input.top - height -
2754
input.bottom) / 2 + input.top;
2760
if (state & CompWindowStateMaximizedHorzMask)
2762
if (old.x () < x + workArea.x () + input.left)
2764
xwc->x = x + workArea.x () + input.left;
2769
width = xwc->width + old.border () * 2;
2771
max = x + workArea.right ();
2772
if (old.x () + (int) old.width () + input.right > max)
2774
xwc->x = max - width - input.right;
2777
else if (old.x () + width + input.right > max)
2779
xwc->x = x + workArea.x () +
2780
(workArea.width () - input.left - width -
2781
input.right) / 2 + input.left;
2789
if ((mask & CWX) && (xwc->x == old.x ()))
2792
if ((mask & CWY) && (xwc->y == old.y ()))
2795
if ((mask & CWWidth) && (xwc->width == (int) old.width ()))
2798
if ((mask & CWHeight) && (xwc->height == (int) old.height ()))
2805
PrivateWindow::adjustConfigureRequestForGravity (XWindowChanges *xwc,
2811
unsigned int mask = 0;
2816
if (xwcm & (CWX | CWWidth))
2819
case NorthWestGravity:
2821
case SouthWestGravity:
2823
newX += priv->input.left * direction;
2830
newX -= (xwc->width / 2 - priv->input.left +
2831
(priv->input.left + priv->input.right) / 2) * direction;
2833
newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2836
case NorthEastGravity:
2838
case SouthEastGravity:
2840
newX -= xwc->width + priv->input.right * direction;
2842
newX -= (xwc->width - priv->serverGeometry.width ()) * direction;
2851
if (xwcm & (CWY | CWHeight))
2854
case NorthWestGravity:
2856
case NorthEastGravity:
2858
newY = xwc->y + priv->input.top * direction;
2865
newY -= (xwc->height / 2 - priv->input.top +
2866
(priv->input.top + priv->input.bottom) / 2) * direction;
2868
newY -= ((xwc->height - priv->serverGeometry.height ()) / 2) * direction;
2871
case SouthWestGravity:
2873
case SouthEastGravity:
2875
newY -= xwc->height + priv->input.bottom * direction;
2877
newY -= (xwc->height - priv->serverGeometry.height ()) * direction;
2888
xwc->x += (newX - xwc->x);
2894
xwc->y += (newY - xwc->y);
2902
CompWindow::moveResize (XWindowChanges *xwc,
2905
unsigned int source)
2907
bool placed = false;
2909
xwcm &= (CWX | CWY | CWWidth | CWHeight | CWBorderWidth);
2911
if (xwcm & (CWX | CWY))
2912
if (priv->sizeHints.flags & (USPosition | PPosition))
2916
gravity = priv->sizeHints.win_gravity;
2919
xwc->x = priv->serverGeometry.x ();
2921
xwc->y = priv->serverGeometry.y ();
2922
if (!(xwcm & CWWidth))
2923
xwc->width = priv->serverGeometry.width ();
2924
if (!(xwcm & CWHeight))
2925
xwc->height = priv->serverGeometry.height ();
2927
if (xwcm & (CWWidth | CWHeight))
2931
if (constrainNewWindowSize (xwc->width, xwc->height, &width, &height))
2933
if (width != xwc->width)
2936
if (height != xwc->height)
2940
xwc->height = height;
2944
xwcm |= priv->adjustConfigureRequestForGravity (xwc, xwcm, gravity, 1);
2946
validateResizeRequest (xwcm, xwc, source);
2948
/* when horizontally maximized only allow width changes added by
2949
addWindowSizeChanges */
2950
if (priv->state & CompWindowStateMaximizedHorzMask)
2953
/* when vertically maximized only allow height changes added by
2954
addWindowSizeChanges */
2955
if (priv->state & CompWindowStateMaximizedVertMask)
2958
xwcm |= priv->addWindowSizeChanges (xwc, Geometry (xwc->x, xwc->y,
2959
xwc->width, xwc->height,
2960
xwc->border_width));
2962
/* check if the new coordinates are useful and valid (different
2963
to current size); if not, we have to clear them to make sure
2964
we send a synthetic ConfigureNotify event if all coordinates
2965
match the server coordinates */
2966
if (xwc->x == priv->serverGeometry.x ())
2969
if (xwc->y == priv->serverGeometry.y ())
2972
if (xwc->width == (int) priv->serverGeometry.width ())
2975
if (xwc->height == (int) priv->serverGeometry.height ())
2978
if (xwc->border_width == (int) priv->serverGeometry.border ())
2979
xwcm &= ~CWBorderWidth;
2981
/* update saved window coordinates - if CWX or CWY is set for fullscreen
2982
or maximized windows after addWindowSizeChanges, it should be pretty
2983
safe to assume that the saved coordinates should be updated too, e.g.
2984
because the window was moved to another viewport by some client */
2985
if ((xwcm & CWX) && (priv->saveMask & CWX))
2986
priv->saveWc.x += (xwc->x - priv->serverGeometry.x ());
2988
if ((xwcm & CWY) && (priv->saveMask & CWY))
2989
priv->saveWc.y += (xwc->y - priv->serverGeometry.y ());
2991
if (priv->mapNum && (xwcm & (CWWidth | CWHeight)))
2995
configureXWindow (xwcm, xwc);
2998
/* we have to send a configure notify on ConfigureRequest events if
2999
we decide not to do anything according to ICCCM 4.1.5 */
3000
sendConfigureNotify ();
3004
priv->placed = true;
3008
PrivateWindow::updateSize ()
3013
if (window->overrideRedirect () || !managed)
3016
mask = priv->addWindowSizeChanges (&xwc, priv->serverGeometry);
3019
if (priv->mapNum && (mask & (CWWidth | CWHeight)))
3020
window->sendSyncRequest ();
3022
window->configureXWindow (mask, &xwc);
3027
PrivateWindow::addWindowStackChanges (XWindowChanges *xwc,
3028
CompWindow *sibling)
3032
if (!sibling || sibling->priv->id != id)
3038
XLowerWindow (screen->dpy (), id);
3040
XLowerWindow (screen->dpy (), frame);
3042
/* Restacking of compiz's window list happens
3043
immediately and since this path doesn't call
3044
reconfigureXWindow, restack must be called here. */
3047
else if (sibling->priv->id != window->prev->priv->id)
3049
mask |= CWSibling | CWStackMode;
3051
xwc->stack_mode = Above;
3052
xwc->sibling = ROOTPARENT (sibling);
3057
mask |= CWSibling | CWStackMode;
3059
xwc->stack_mode = Above;
3060
xwc->sibling = ROOTPARENT (sibling);
3064
if (sibling && mask)
3066
/* a normal window can be stacked above fullscreen windows but we
3067
don't want normal windows to be stacked above dock window so if
3068
the sibling we're stacking above is a fullscreen window we also
3069
update all dock windows. */
3070
if ((sibling->priv->type & CompWindowTypeFullscreenMask) &&
3071
(!(type & (CompWindowTypeFullscreenMask |
3072
CompWindowTypeDockMask))) &&
3073
!isAncestorTo (window, sibling))
3077
for (dw = screen->windows ().back (); dw; dw = dw->prev)
3081
/* Collect all dock windows first */
3082
CompWindowList dockWindows;
3083
for (; dw; dw = dw->prev)
3084
if (dw->priv->type & CompWindowTypeDockMask)
3085
dockWindows.push_back (dw);
3087
/* Then update the dock windows */
3088
foreach (CompWindow *dw, dockWindows)
3089
dw->configureXWindow (mask, xwc);
3097
CompWindow::raise ()
3101
bool aboveFs = false;
3103
/* an active fullscreen window should be raised over all other
3104
windows in its layer */
3105
if (priv->type & CompWindowTypeFullscreenMask)
3106
if (priv->id == screen->activeWindow ())
3109
mask = priv->addWindowStackChanges (&xwc,
3110
PrivateWindow::findSiblingBelow (this, aboveFs));
3113
configureXWindow (mask, &xwc);
3117
PrivateScreen::focusTopMostWindow ()
3119
CompWindow *focus = NULL;
3120
CompWindowList::reverse_iterator it = windows.rbegin ();
3122
for (; it != windows.rend (); it++)
3124
CompWindow *w = *it;
3126
if (w->type () & CompWindowTypeDockMask)
3138
if (focus->id () != activeWindow)
3139
focus->moveInputFocusTo ();
3142
XSetInputFocus (dpy, root, RevertToPointerRoot,
3149
CompWindow::lower ()
3154
mask = priv->addWindowStackChanges (&xwc,
3155
PrivateWindow::findLowestSiblingBelow (this));
3157
configureXWindow (mask, &xwc);
3159
/* when lowering a window, focus the topmost window if
3160
the click-to-focus option is on */
3161
if ((screen->priv->optionGetClickToFocus ()))
3163
Window aboveWindowId = prev ? prev->id () : None;
3164
screen->unhookWindow (this);
3165
CompWindow *focusedWindow = screen->priv->focusTopMostWindow ();
3166
screen->insertWindow (this , aboveWindowId);
3168
/* if the newly focused window is a desktop window,
3169
give the focus back to w */
3170
if (focusedWindow &&
3171
focusedWindow->type () & CompWindowTypeDesktopMask)
3173
moveInputFocusTo ();
3179
CompWindow::restackAbove (CompWindow *sibling)
3181
for (; sibling; sibling = sibling->next)
3182
if (PrivateWindow::validSiblingBelow (this, sibling))
3190
mask = priv->addWindowStackChanges (&xwc, sibling);
3192
configureXWindow (mask, &xwc);
3196
/* finds the highest window under sibling we can stack above */
3198
PrivateWindow::findValidStackSiblingBelow (CompWindow *w,
3199
CompWindow *sibling)
3201
CompWindow *lowest, *last, *p;
3203
/* check whether we're allowed to stack under a sibling by finding
3204
* the above 'sibling' and checking whether or not we're allowed
3205
* to stack under that - if not, then there is no valid sibling
3208
for (p = sibling; p; p = p->next)
3210
if (!avoidStackingRelativeTo (p))
3212
if (!validSiblingBelow (p, w))
3218
/* get lowest sibling we're allowed to stack above */
3219
lowest = last = findLowestSiblingBelow (w);
3221
/* walk from bottom up */
3222
for (p = screen->windows ().front (); p; p = p->next)
3224
/* stop walking when we reach the sibling we should try to stack
3229
/* skip windows that we should avoid */
3230
if (w == p || avoidStackingRelativeTo (p))
3233
if (validSiblingBelow (w, p))
3235
/* update lowest as we find windows below sibling that we're
3236
allowed to stack above. last window must be equal to the
3237
lowest as we shouldn't update lowest if we passed an
3243
/* update last pointer */
3251
CompWindow::restackBelow (CompWindow *sibling)
3256
mask = priv->addWindowStackChanges (&xwc,
3257
PrivateWindow::findValidStackSiblingBelow (this, sibling));
3260
configureXWindow (mask, &xwc);
3264
CompWindow::updateAttributes (CompStackingUpdateMode stackingMode)
3269
if (overrideRedirect () || !priv->managed)
3272
if (priv->state & CompWindowStateShadedMask)
3274
windowNotify (CompWindowNotifyShade);
3278
else if (priv->shaded)
3280
windowNotify (CompWindowNotifyUnshade);
3285
if (stackingMode != CompStackingUpdateModeNone)
3288
CompWindow *sibling;
3290
aboveFs = (stackingMode == CompStackingUpdateModeAboveFullscreen);
3291
if (priv->type & CompWindowTypeFullscreenMask)
3293
/* put active or soon-to-be-active fullscreen windows over
3294
all others in their layer */
3295
if (priv->id == screen->activeWindow ())
3301
/* put windows that are just mapped, over fullscreen windows */
3302
if (stackingMode == CompStackingUpdateModeInitialMap)
3305
sibling = PrivateWindow::findSiblingBelow (this, aboveFs);
3308
(stackingMode == CompStackingUpdateModeInitialMapDeniedFocus))
3312
for (p = sibling; p; p = p->prev)
3313
if (p->priv->id == screen->activeWindow ())
3316
/* window is above active window so we should lower it,
3317
* assuing that is allowed (if, for example, our window has
3318
* the "above" state, then lowering beneath the active
3319
* window may not be allowed). */
3320
if (p && PrivateWindow::validSiblingBelow (p, this))
3322
p = PrivateWindow::findValidStackSiblingBelow (sibling, p);
3324
/* if we found a valid sibling under the active window, it's
3325
our new sibling we want to stack above */
3331
mask |= priv->addWindowStackChanges (&xwc, sibling);
3334
if ((stackingMode == CompStackingUpdateModeInitialMap) ||
3335
(stackingMode == CompStackingUpdateModeInitialMapDeniedFocus))
3337
/* If we are called from the MapRequest handler, we have to
3338
immediately update the internal stack. If we don't do that,
3339
the internal stacking order is invalid until the ConfigureNotify
3340
arrives because we put the window at the top of the stack when
3342
if (mask & CWStackMode)
3344
Window above = (mask & CWSibling) ? xwc.sibling : 0;
3345
priv->restack (above);
3349
mask |= priv->addWindowSizeChanges (&xwc, priv->serverGeometry);
3351
if (priv->mapNum && (mask & (CWWidth | CWHeight)))
3355
configureXWindow (mask, &xwc);
3359
PrivateWindow::ensureWindowVisibility ()
3362
int width = serverGeometry.width () + serverGeometry.border () * 2;
3363
int height = serverGeometry.height () + serverGeometry.border () * 2;
3367
if (struts || attrib.override_redirect)
3370
if (type & (CompWindowTypeDockMask |
3371
CompWindowTypeFullscreenMask |
3372
CompWindowTypeUnknownMask))
3375
x1 = screen->workArea ().x () - screen->width () * screen->vp ().x ();
3376
y1 = screen->workArea ().y () - screen->height () * screen->vp ().y ();
3377
x2 = x1 + screen->workArea ().width () + screen->vpSize ().width () *
3379
y2 = y1 + screen->workArea ().height () + screen->vpSize ().height () *
3382
if (serverGeometry.x () - input.left >= x2)
3383
dx = (x2 - 25) - serverGeometry.x ();
3384
else if (serverGeometry.x () + width + input.right <= x1)
3385
dx = (x1 + 25) - (serverGeometry.x () + width);
3387
if (serverGeometry.y () - input.top >= y2)
3388
dy = (y2 - 25) - serverGeometry.y ();
3389
else if (serverGeometry.y () + height + input.bottom <= y1)
3390
dy = (y1 + 25) - (serverGeometry.y () + height);
3396
xwc.x = serverGeometry.x () + dx;
3397
xwc.y = serverGeometry.y () + dy;
3399
window->configureXWindow (CWX | CWY, &xwc);
3404
PrivateWindow::reveal ()
3406
if (window->minimized ())
3407
window->unminimize ();
3409
screen->leaveShowDesktopMode (window);
3413
PrivateWindow::revealAncestors (CompWindow *w,
3414
CompWindow *transient)
3416
if (isAncestorTo (transient, w))
3418
screen->forEachWindow (boost::bind (revealAncestors, _1, w));
3424
CompWindow::activate ()
3426
WRAPABLE_HND_FUNC (3, activate)
3428
screen->priv->setCurrentDesktop (priv->desktop);
3430
screen->forEachWindow (
3431
boost::bind (PrivateWindow::revealAncestors, _1, this));
3434
if (priv->state & CompWindowStateHiddenMask)
3436
priv->state &= ~CompWindowStateShadedMask;
3441
if (priv->state & CompWindowStateHiddenMask)
3444
if (!onCurrentDesktop ())
3447
priv->ensureWindowVisibility ();
3448
updateAttributes (CompStackingUpdateModeAboveFullscreen);
3449
moveInputFocusTo ();
3453
#define PVertResizeInc (1 << 0)
3454
#define PHorzResizeInc (1 << 1)
3457
CompWindow::constrainNewWindowSize (int width,
3462
const XSizeHints *hints = &priv->sizeHints;
3463
int oldWidth = width;
3464
int oldHeight = height;
3468
int base_height = 0;
3471
int max_width = MAXSHORT;
3472
int max_height = MAXSHORT;
3473
long flags = hints->flags;
3474
long resizeIncFlags = (flags & PResizeInc) ? ~0 : 0;
3476
if (screen->priv->optionGetIgnoreHintsWhenMaximized ())
3478
if (priv->state & MAXIMIZE_STATE)
3482
if (priv->state & CompWindowStateMaximizedHorzMask)
3483
resizeIncFlags &= ~PHorzResizeInc;
3485
if (priv->state & CompWindowStateMaximizedVertMask)
3486
resizeIncFlags &= ~PVertResizeInc;
3490
/* Ater gdk_window_constrain_size(), which is partially borrowed from fvwm.
3492
* Copyright 1993, Robert Nation
3493
* You may use this code for any purpose, as long as the original
3494
* copyright remains in the source code and all documentation
3496
* which in turn borrows parts of the algorithm from uwm
3499
#define FLOOR(value, base) (((int) ((value) / (base))) * (base))
3500
#define FLOOR64(value, base) (((uint64_t) ((value) / (base))) * (base))
3502
if ((flags & PBaseSize) && (flags & PMinSize))
3504
base_width = hints->base_width;
3505
base_height = hints->base_height;
3506
min_width = hints->min_width;
3507
min_height = hints->min_height;
3509
else if (flags & PBaseSize)
3511
base_width = hints->base_width;
3512
base_height = hints->base_height;
3513
min_width = hints->base_width;
3514
min_height = hints->base_height;
3516
else if (flags & PMinSize)
3518
base_width = hints->min_width;
3519
base_height = hints->min_height;
3520
min_width = hints->min_width;
3521
min_height = hints->min_height;
3524
if (flags & PMaxSize)
3526
max_width = hints->max_width;
3527
max_height = hints->max_height;
3530
if (resizeIncFlags & PHorzResizeInc)
3531
xinc = MAX (xinc, hints->width_inc);
3533
if (resizeIncFlags & PVertResizeInc)
3534
yinc = MAX (yinc, hints->height_inc);
3536
/* clamp width and height to min and max values */
3537
width = CLAMP (width, min_width, max_width);
3538
height = CLAMP (height, min_height, max_height);
3540
/* shrink to base + N * inc */
3541
width = base_width + FLOOR (width - base_width, xinc);
3542
height = base_height + FLOOR (height - base_height, yinc);
3544
/* constrain aspect ratio, according to:
3546
* min_aspect.x width max_aspect.x
3547
* ------------ <= -------- <= -----------
3548
* min_aspect.y height max_aspect.y
3550
if ((flags & PAspect) && hints->min_aspect.y > 0 && hints->max_aspect.x > 0)
3552
/* Use 64 bit arithmetic to prevent overflow */
3554
uint64_t min_aspect_x = hints->min_aspect.x;
3555
uint64_t min_aspect_y = hints->min_aspect.y;
3556
uint64_t max_aspect_x = hints->max_aspect.x;
3557
uint64_t max_aspect_y = hints->max_aspect.y;
3560
if (min_aspect_x * height > width * min_aspect_y)
3562
delta = FLOOR64 (height - width * min_aspect_y / min_aspect_x,
3564
if (height - (int) delta >= min_height)
3568
delta = FLOOR64 (height * min_aspect_x / min_aspect_y - width,
3570
if (width + (int) delta <= max_width)
3575
if (width * max_aspect_y > max_aspect_x * height)
3577
delta = FLOOR64 (width - height * max_aspect_x / max_aspect_y,
3579
if (width - (int) delta >= min_width)
3583
delta = FLOOR64 (width * min_aspect_y / min_aspect_x - height,
3585
if (height + (int) delta <= max_height)
3595
if (width != oldWidth || height != oldHeight)
3598
*newHeight = height;
3609
priv->hidden = true;
3616
priv->hidden = false;
3621
PrivateWindow::hide ()
3623
bool onDesktop = window->onCurrentDesktop ();
3628
if (!window->minimized () && !inShowDesktopMode &&
3629
!hidden && onDesktop)
3631
if (state & CompWindowStateShadedMask)
3644
if ((state & CompWindowStateShadedMask) && frame)
3645
XUnmapWindow (screen->dpy (), frame);
3648
if (!pendingMaps && !window->isViewable ())
3651
window->windowNotify (CompWindowNotifyHide);
3655
if (frame && !shaded)
3656
XUnmapWindow (screen->dpy (), frame);
3658
XUnmapWindow (screen->dpy (), id);
3660
if (window->minimized () || inShowDesktopMode || hidden || shaded)
3661
window->changeState (state | CompWindowStateHiddenMask);
3663
if (shaded && id == screen->activeWindow ())
3664
window->moveInputFocusTo ();
3668
PrivateWindow::show ()
3670
bool onDesktop = window->onCurrentDesktop ();
3675
if (minimized || inShowDesktopMode ||
3676
hidden || !onDesktop)
3678
/* no longer hidden but not on current desktop */
3679
if (!minimized && !inShowDesktopMode && !hidden)
3680
window->changeState (state & ~CompWindowStateHiddenMask);
3685
/* transition from minimized to shaded */
3686
if (state & CompWindowStateShadedMask)
3691
XMapWindow (screen->dpy (), frame);
3694
window->resize (attrib.x, attrib.y,
3695
attrib.width, ++attrib.height - 1,
3696
attrib.border_width);
3705
window->windowNotify (CompWindowNotifyShow);
3711
XMapWindow (screen->dpy (), frame);
3712
XMapWindow (screen->dpy (), wrapper);
3715
XMapWindow (screen->dpy (), id);
3717
window->changeState (state & ~CompWindowStateHiddenMask);
3718
screen->priv->setWindowState (state, id);
3722
PrivateWindow::minimizeTransients (CompWindow *w,
3723
CompWindow *ancestor)
3725
if (w->priv->transientFor == ancestor->priv->id ||
3726
w->priv->isGroupTransient (ancestor->priv->clientLeader))
3733
CompWindow::minimize ()
3735
WRAPABLE_HND_FUNC (13, minimize);
3740
if (!priv->minimized)
3742
windowNotify (CompWindowNotifyMinimize);
3744
priv->minimized = true;
3746
screen->forEachWindow (
3747
boost::bind (PrivateWindow::minimizeTransients, _1, this));
3754
PrivateWindow::unminimizeTransients (CompWindow *w,
3755
CompWindow *ancestor)
3757
if (w->priv->transientFor == ancestor->priv->id ||
3758
w->priv->isGroupTransient (ancestor->priv->clientLeader))
3763
CompWindow::unminimize ()
3765
WRAPABLE_HND_FUNC (14, unminimize);
3766
if (priv->minimized)
3768
windowNotify (CompWindowNotifyUnminimize);
3770
priv->minimized = false;
3774
screen->forEachWindow (
3775
boost::bind (PrivateWindow::unminimizeTransients, _1, this));
3780
CompWindow::maximize (unsigned int state)
3782
if (overrideRedirect ())
3785
state = constrainWindowState (state, priv->actions);
3787
state &= MAXIMIZE_STATE;
3789
if (state == (priv->state & MAXIMIZE_STATE))
3792
state |= (priv->state & ~MAXIMIZE_STATE);
3794
changeState (state);
3795
updateAttributes (CompStackingUpdateModeNone);
3799
PrivateWindow::getUserTime (Time& time)
3803
unsigned long n, left;
3804
unsigned char *data;
3805
bool retval = false;
3807
result = XGetWindowProperty (screen->dpy (), priv->id,
3809
0L, 1L, False, XA_CARDINAL, &actual, &format,
3812
if (result == Success && data)
3818
memcpy (&value, data, sizeof (CARD32));
3820
time = (Time) value;
3823
XFree ((void *) data);
3830
PrivateWindow::setUserTime (Time time)
3832
CARD32 value = (CARD32) time;
3834
XChangeProperty (screen->dpy (), priv->id,
3836
XA_CARDINAL, 32, PropModeReplace,
3837
(unsigned char *) &value, 1);
3841
* Macros from metacity
3843
* Xserver time can wraparound, thus comparing two timestamps needs to
3844
* take this into account. Here's a little macro to help out. If no
3845
* wraparound has occurred, this is equivalent to
3847
* Of course, the rest of the ugliness of this macro comes from
3848
* accounting for the fact that wraparound can occur and the fact that
3849
* a timestamp of 0 must be special-cased since it means older than
3852
* Note that this is NOT an equivalent for time1 <= time2; if that's
3853
* what you need then you'll need to swap the order of the arguments
3854
* and negate the result.
3856
#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
3857
( (( (time1) < (time2) ) && \
3858
( (time2) - (time1) < ((unsigned long) -1) / 2 )) || \
3859
(( (time1) > (time2) ) && \
3860
( (time1) - (time2) > ((unsigned long) -1) / 2 )) \
3862
#define XSERVER_TIME_IS_BEFORE(time1, time2) \
3864
(XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS (time1, time2) && \
3869
PrivateWindow::getUsageTimestamp (Time& timestamp)
3871
if (getUserTime (timestamp))
3874
if (initialTimestampSet)
3876
timestamp = initialTimestamp;
3884
PrivateWindow::isWindowFocusAllowed (Time timestamp)
3886
CompScreen *s = screen;
3888
Time wUserTime, aUserTime;
3889
bool gotTimestamp = false;
3893
level = s->priv->optionGetFocusPreventionLevel ();
3895
if (level == CoreOptions::FocusPreventionLevelOff)
3900
/* the caller passed a timestamp, so use that
3901
instead of the window's user time */
3902
wUserTime = timestamp;
3903
gotTimestamp = true;
3907
gotTimestamp = getUsageTimestamp (wUserTime);
3910
/* if we got no timestamp for the window, try to get at least a timestamp
3911
for its transient parent, if any */
3912
if (!gotTimestamp && transientFor)
3916
parent = screen->findWindow (transientFor);
3918
gotTimestamp = parent->priv->getUsageTimestamp (wUserTime);
3921
if (gotTimestamp && !wUserTime)
3923
/* window explicitly requested no focus */
3927
/* allow focus for excluded windows */
3928
CompMatch &match = s->priv->optionGetFocusPreventionMatch ();
3929
if (!match.evaluate (window))
3932
if (level == CoreOptions::FocusPreventionLevelVeryHigh)
3935
active = s->findWindow (s->activeWindow ());
3937
/* no active window */
3938
if (!active || (active->type () & CompWindowTypeDesktopMask))
3941
/* active window belongs to same application */
3942
if (window->clientLeader () == active->clientLeader ())
3945
if (level == CoreOptions::FocusPreventionLevelHigh)
3948
/* not in current viewport or desktop */
3949
if (!window->onCurrentDesktop ())
3952
dvp = window->defaultViewport ();
3953
if (dvp.x () != s->vp ().x () || dvp.y () != s->vp ().y ())
3958
/* unsure as we have nothing to compare - allow focus in low level,
3959
don't allow in normal level */
3960
if (level == CoreOptions::FocusPreventionLevelNormal)
3966
/* can't get user time for active window */
3967
if (!active->priv->getUserTime (aUserTime))
3970
if (XSERVER_TIME_IS_BEFORE (wUserTime, aUserTime))
3977
PrivateWindow::allowWindowFocus (unsigned int noFocusMask,
3982
if (priv->id == screen->activeWindow ())
3985
/* do not focus windows of these types */
3986
if (priv->type & noFocusMask)
3989
/* window doesn't take focus */
3990
if (!priv->inputHint &&
3991
!(priv->protocols & CompWindowProtocolTakeFocusMask))
3996
retval = priv->isWindowFocusAllowed (timestamp);
3999
/* add demands attention state if focus was prevented */
4000
window->changeState (priv->state | CompWindowStateDemandsAttentionMask);
4007
CompWindow::defaultViewport ()
4011
if (priv->serverGeometry.x () < (int) screen->width () &&
4012
priv->serverGeometry.x () + priv->serverGeometry.width () > 0 &&
4013
priv->serverGeometry.y () < (int) screen->height () &&
4014
priv->serverGeometry.y ()+ priv->serverGeometry.height () > 0)
4016
return screen->vp ();
4019
screen->viewportForGeometry (priv->serverGeometry, viewport);
4025
CompWindow::initialViewport () const
4027
return priv->initialViewport;
4031
PrivateWindow::readIconHint ()
4033
XImage *image, *maskImage = NULL;
4034
Display *dpy = screen->dpy ();
4035
unsigned int width, height, dummy;
4036
unsigned int i, j, k;
4043
if (!XGetGeometry (dpy, hints->icon_pixmap, &wDummy, &iDummy,
4044
&iDummy, &width, &height, &dummy, &dummy))
4047
image = XGetImage (dpy, hints->icon_pixmap, 0, 0, width, height,
4048
AllPlanes, ZPixmap);
4052
colors = new XColor[width * height];
4055
XDestroyImage (image);
4060
for (j = 0; j < height; j++)
4061
for (i = 0; i < width; i++)
4062
colors[k++].pixel = XGetPixel (image, i, j);
4064
for (i = 0; i < k; i += 256)
4065
XQueryColors (dpy, screen->priv->colormap,
4066
&colors[i], MIN (k - i, 256));
4068
XDestroyImage (image);
4070
icon = new CompIcon (screen, width, height);
4077
if (hints->flags & IconMaskHint)
4078
maskImage = XGetImage (dpy, hints->icon_mask, 0, 0,
4079
width, height, AllPlanes, ZPixmap);
4082
p = (CARD32 *) icon->data ();
4084
for (j = 0; j < height; j++)
4086
for (i = 0; i < width; i++)
4088
if (maskImage && !XGetPixel (maskImage, i, j))
4090
else if (image->depth == 1) /* white : black */
4091
*p++ = colors[k].pixel ? 0xffffffff : 0xff000000;
4093
*p++ = 0xff000000 | /* alpha */
4094
(((colors[k].red >> 8) & 0xff) << 16) | /* red */
4095
(((colors[k].green >> 8) & 0xff) << 8) | /* green */
4096
((colors[k].blue >> 8) & 0xff); /* blue */
4104
XDestroyImage (maskImage);
4106
icons.push_back (icon);
4109
/* returns icon with dimensions as close as possible to width and height
4110
but never greater. */
4112
CompWindow::getIcon (int width,
4116
int wh, diff, oldDiff;
4119
/* need to fetch icon property */
4120
if (priv->icons.size () == 0 && !priv->noIcons)
4124
unsigned long n, left;
4125
unsigned char *data;
4127
result = XGetWindowProperty (screen->dpy (), priv->id, Atoms::wmIcon,
4128
0L, 65536L, false, XA_CARDINAL,
4129
&actual, &format, &n, &left, &data);
4131
if (result == Success && data)
4134
CARD32 alpha, red, green, blue;
4135
unsigned long iw, ih;
4137
for (i = 0; i + 2 < n; i += iw * ih + 2)
4139
unsigned long *idata = (unsigned long *) data;
4144
/* iw * ih may be larger than the value range of unsigned
4145
* long, so better do some checking for extremely weird
4146
* icon sizes first */
4147
if (iw > 2048 || ih > 2048 || iw * ih + 2 > n - i)
4153
icon = new CompIcon (screen, iw, ih);
4157
priv->icons.push_back (icon);
4159
p = (CARD32 *) (icon->data ());
4161
/* EWMH doesn't say if icon data is premultiplied or
4162
not but most applications seem to assume data should
4163
be unpremultiplied. */
4164
for (j = 0; j < iw * ih; j++)
4166
alpha = (idata[i + j + 2] >> 24) & 0xff;
4167
red = (idata[i + j + 2] >> 16) & 0xff;
4168
green = (idata[i + j + 2] >> 8) & 0xff;
4169
blue = (idata[i + j + 2] >> 0) & 0xff;
4171
red = (red * alpha) >> 8;
4172
green = (green * alpha) >> 8;
4173
blue = (blue * alpha) >> 8;
4186
else if (priv->hints && (priv->hints->flags & IconPixmapHint))
4188
priv->readIconHint ();
4191
/* don't fetch property again */
4192
if (priv->icons.size () == 0)
4193
priv->noIcons = true;
4196
/* no icons available for this window */
4201
wh = width + height;
4203
for (i = 0; i < priv->icons.size (); i++)
4205
const CompSize iconSize = *priv->icons[i];
4207
if ((int) iconSize.width () > width ||
4208
(int) iconSize.height () > height)
4213
diff = wh - (iconSize.width () + iconSize.height ());
4214
oldDiff = wh - (icon->width () + icon->height ());
4217
icon = priv->icons[i];
4220
icon = priv->icons[i];
4227
CompWindow::iconGeometry () const
4229
return priv->iconGeometry;
4233
PrivateWindow::freeIcons ()
4235
for (unsigned int i = 0; i < priv->icons.size (); i++)
4236
delete priv->icons[i];
4238
priv->icons.resize (0);
4239
priv->noIcons = false;
4243
CompWindow::outputDevice ()
4245
return screen->outputDeviceForGeometry (priv->serverGeometry);
4249
CompWindow::onCurrentDesktop ()
4251
if (priv->desktop == 0xffffffff ||
4252
priv->desktop == screen->currentDesktop ())
4261
CompWindow::setDesktop (unsigned int desktop)
4263
if (desktop != 0xffffffff)
4265
if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4268
if (desktop >= screen->nDesktop ())
4272
if (desktop == priv->desktop)
4275
priv->desktop = desktop;
4277
if (desktop == 0xffffffff || desktop == screen->currentDesktop ())
4282
screen->setWindowProp (priv->id, Atoms::winDesktop, priv->desktop);
4285
/* The compareWindowActiveness function compares the two windows 'w1'
4286
and 'w2'. It returns an integer less than, equal to, or greater
4287
than zero if 'w1' is found, respectively, to activated longer time
4288
ago than, to be activated at the same time, or be activated more
4289
recently than 'w2'. */
4291
PrivateWindow::compareWindowActiveness (CompWindow *w1,
4294
CompActiveWindowHistory *history = screen->currentHistory ();
4297
/* check current window history first */
4298
for (i = 0; i < ACTIVE_WINDOW_HISTORY_SIZE; i++)
4300
if (history->id[i] == w1->priv->id)
4303
if (history->id[i] == w2->priv->id)
4306
if (!history->id[i])
4310
return w1->priv->activeNum - w2->priv->activeNum;
4314
CompWindow::onAllViewports ()
4316
if (overrideRedirect ())
4319
if (!priv->managed && !isViewable ())
4322
if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4325
if (priv->state & CompWindowStateStickyMask)
4332
CompWindow::getMovementForOffset (CompPoint offset)
4334
CompScreen *s = screen;
4335
int m, vWidth, vHeight;
4336
int offX = offset.x (), offY = offset.y ();
4339
vWidth = s->width () * s->vpSize ().width ();
4340
vHeight = s->height () * s->vpSize ().height ();
4346
if (s->vpSize ().width () == 1)
4352
m = priv->attrib.x + offX;
4353
if (m - priv->input.left < (int) s->width () - vWidth)
4354
rv.setX (offX + vWidth);
4355
else if (m + priv->width + priv->input.right > vWidth)
4356
rv.setX (offX - vWidth);
4361
if (s->vpSize ().height () == 1)
4367
m = priv->attrib.y + offY;
4368
if (m - priv->input.top < (int) s->height () - vHeight)
4369
rv.setY (offY + vHeight);
4370
else if (m + priv->height + priv->input.bottom > vHeight)
4371
rv.setY (offY - vHeight);
4380
WindowInterface::getOutputExtents (CompWindowExtents& output)
4381
WRAPABLE_DEF (getOutputExtents, output)
4384
WindowInterface::getAllowedActions (unsigned int &setActions,
4385
unsigned int &clearActions)
4386
WRAPABLE_DEF (getAllowedActions, setActions, clearActions)
4389
WindowInterface::focus ()
4390
WRAPABLE_DEF (focus)
4393
WindowInterface::activate ()
4394
WRAPABLE_DEF (activate)
4397
WindowInterface::place (CompPoint &pos)
4398
WRAPABLE_DEF (place, pos)
4401
WindowInterface::validateResizeRequest (unsigned int &mask,
4402
XWindowChanges *xwc,
4403
unsigned int source)
4404
WRAPABLE_DEF (validateResizeRequest, mask, xwc, source)
4407
WindowInterface::resizeNotify (int dx,
4411
WRAPABLE_DEF (resizeNotify, dx, dy, dwidth, dheight)
4414
WindowInterface::moveNotify (int dx,
4417
WRAPABLE_DEF (moveNotify, dx, dy, immediate)
4420
WindowInterface::windowNotify (CompWindowNotify n)
4421
WRAPABLE_DEF (windowNotify, n)
4424
WindowInterface::grabNotify (int x,
4428
WRAPABLE_DEF (grabNotify, x, y, state, mask)
4431
WindowInterface::ungrabNotify ()
4432
WRAPABLE_DEF (ungrabNotify)
4435
WindowInterface::stateChangeNotify (unsigned int lastState)
4436
WRAPABLE_DEF (stateChangeNotify, lastState)
4439
WindowInterface::updateFrameRegion (CompRegion ®ion)
4440
WRAPABLE_DEF (updateFrameRegion, region)
4443
WindowInterface::minimize ()
4444
WRAPABLE_DEF (minimize);
4447
WindowInterface::unminimize ()
4448
WRAPABLE_DEF (unminimize);
4451
WindowInterface::minimized ()
4452
WRAPABLE_DEF (minimized);
4455
WindowInterface::alpha ()
4456
WRAPABLE_DEF (alpha);
4459
WindowInterface::isFocussable ()
4460
WRAPABLE_DEF (isFocussable);
4463
WindowInterface::managed ()
4464
WRAPABLE_DEF (managed);
4479
CompWindow::state ()
4485
CompWindow::actions ()
4487
return priv->actions;
4491
CompWindow::protocols ()
4493
return priv->protocols;
4497
CompWindow::close (Time serverTime)
4499
if (serverTime == 0)
4500
serverTime = screen->getCurrentTime ();
4504
if (priv->protocols & CompWindowProtocolDeleteMask)
4508
ev.type = ClientMessage;
4509
ev.xclient.window = priv->id;
4510
ev.xclient.message_type = Atoms::wmProtocols;
4511
ev.xclient.format = 32;
4512
ev.xclient.data.l[0] = Atoms::wmDeleteWindow;
4513
ev.xclient.data.l[1] = serverTime;
4514
ev.xclient.data.l[2] = 0;
4515
ev.xclient.data.l[3] = 0;
4516
ev.xclient.data.l[4] = 0;
4518
XSendEvent (screen->dpy (), priv->id, false, NoEventMask, &ev);
4522
XKillClient (screen->dpy (), priv->id);
4525
priv->closeRequests++;
4529
screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4530
serverTime, priv->id, true, 0, 0);
4533
priv->lastCloseRequestTime = serverTime;
4537
PrivateWindow::handlePingTimeout (unsigned int lastPing)
4539
if (!window->isViewable ())
4542
if (!(priv->type & CompWindowTypeNormalMask))
4545
if (priv->protocols & CompWindowProtocolPingMask)
4547
if (priv->transientFor)
4550
if (priv->lastPong < lastPing)
4554
priv->alive = false;
4556
window->windowNotify (CompWindowNotifyAliveChanged);
4558
if (priv->closeRequests)
4560
screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4561
priv->lastCloseRequestTime,
4562
priv->id, true, 0, 0);
4564
priv->closeRequests = 0;
4575
PrivateWindow::handlePing (int lastPing)
4581
window->windowNotify (CompWindowNotifyAliveChanged);
4583
if (priv->lastCloseRequestTime)
4585
screen->toolkitAction (Atoms::toolkitActionForceQuitDialog,
4586
priv->lastCloseRequestTime,
4587
priv->id, false, 0, 0);
4589
priv->lastCloseRequestTime = 0;
4592
priv->lastPong = lastPing;
4596
PrivateWindow::processMap ()
4599
bool wasManaged = priv->managed;
4600
CompStackingUpdateMode stackingMode;
4602
priv->initialViewport = screen->vp ();
4604
priv->initialTimestampSet = false;
4606
screen->priv->applyStartupProperties (window);
4610
priv->managed = true;
4614
int gravity = priv->sizeHints.win_gravity;
4618
/* adjust for gravity, but only for frame size */
4619
xwc.x = priv->serverGeometry.x ();
4620
xwc.y = priv->serverGeometry.y ();
4624
xwcm = adjustConfigureRequestForGravity (&xwc, CWX | CWY, gravity, 1);
4626
window->validateResizeRequest (xwcm, &xwc, ClientTypeApplication);
4628
CompPoint pos (xwc.x, xwc.y);
4629
if (window->place (pos))
4637
window->configureXWindow (xwcm, &xwc);
4639
priv->placed = true;
4642
allowFocus = allowWindowFocus (NO_FOCUS_MASK, 0);
4644
if (!allowFocus && (priv->type & ~NO_FOCUS_MASK))
4645
stackingMode = CompStackingUpdateModeInitialMapDeniedFocus;
4647
stackingMode = CompStackingUpdateModeInitialMap;
4649
window->updateAttributes (stackingMode);
4651
/* Window was either minimized by us, or it was mapped again
4652
* since it has gone from withdrawn to iconic state, so
4654
if (window->minimized () && (window->pendingMaps () || wasManaged))
4655
window->unminimize ();
4657
screen->leaveShowDesktopMode (window);
4659
if (allowFocus && !window->onCurrentDesktop ())
4660
screen->priv->setCurrentDesktop (priv->desktop);
4662
if (!(priv->state & CompWindowStateHiddenMask))
4666
window->moveInputFocusTo ();
4670
* PrivateWindow::updatePassiveButtonGrabs
4672
* Updates the passive button grabs for a window. When
4673
* one of the specified button + modifier combinations
4674
* for this window is activated, compiz will be given
4675
* an active grab for the window (which we can turn off
4676
* by calling XAllowEvents later in ::handleEvent)
4678
* NOTE: ICCCM says that we are only allowed to grab
4679
* windows that we actually own as a client, so only
4680
* grab the frame window. Additionally, although there
4681
* isn't anything in the ICCCM that says we cannot
4682
* grab every button, some clients do not interpret
4683
* EnterNotify and LeaveNotify events caused by the
4684
* activation of the grab correctly, so ungrab button
4685
* and modifier combinations that we do not need on
4686
* active windows (but in reality we shouldn't be grabbing
4687
* for buttons that we don't actually need at that point
4692
PrivateWindow::updatePassiveButtonGrabs ()
4694
bool onlyActions = (priv->id == screen->priv->activeWindow ||
4695
!screen->priv->optionGetClickToFocus ());
4700
/* Ungrab everything */
4701
XUngrabButton (screen->priv->dpy, AnyButton, AnyModifier, frame);
4703
/* We don't need the full grab in the following cases:
4704
* - This window has the focus and either
4706
* - we don't want click raise
4711
if (screen->priv->optionGetRaiseOnClick ())
4713
for (CompWindow *above = window->next;
4714
above != NULL; above = above->next)
4716
if (above->priv->attrib.map_state != IsViewable)
4719
if (above->type () & CompWindowTypeDockMask)
4722
if (above->region ().intersects (region))
4724
onlyActions = false;
4733
/* Grab only we have bindings on */
4734
foreach (PrivateScreen::ButtonGrab &bind, screen->priv->buttonGrabs)
4736
unsigned int mods = modHandler->virtualToRealModMask (bind.modifiers);
4738
if (mods & CompNoMask)
4741
for (unsigned int ignore = 0;
4742
ignore <= modHandler->ignoredModMask (); ignore++)
4744
if (ignore & ~modHandler->ignoredModMask ())
4747
XGrabButton (screen->priv->dpy,
4752
ButtonPressMask | ButtonReleaseMask |
4763
/* Grab everything */
4764
XGrabButton (screen->priv->dpy,
4768
ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
4778
CompWindow::region () const
4780
return priv->region;
4784
CompWindow::frameRegion () const
4786
return priv->frameRegion;
4790
CompWindow::inShowDesktopMode ()
4792
return priv->inShowDesktopMode;
4796
CompWindow::setShowDesktopMode (bool value)
4798
priv->inShowDesktopMode = value;
4802
CompWindow::managed ()
4804
WRAPABLE_HND_FUNC_RETURN (18, bool, managed);
4805
return priv->managed;
4809
CompWindow::grabbed ()
4811
return priv->grabbed;
4815
CompWindow::pendingMaps ()
4817
return priv->pendingMaps;
4821
CompWindow::wmType ()
4823
return priv->wmType;
4827
CompWindow::activeNum ()
4829
return priv->activeNum;
4833
CompWindow::frame ()
4839
CompWindow::resName ()
4842
return priv->resName;
4844
return CompString ();
4848
CompWindow::mapNum () const
4850
return priv->mapNum;
4854
CompWindow::struts ()
4856
return priv->struts;
4860
CompWindow::saveMask ()
4862
return priv->saveMask;
4866
CompWindow::saveWc ()
4868
return priv->saveWc;
4872
CompWindow::moveToViewportPosition (int x,
4877
int vWidth = screen->width () * screen->vpSize ().width ();
4878
int vHeight = screen->height () * screen->vpSize ().height ();
4880
if (screen->vpSize ().width () != 1)
4882
x += screen->vp ().x () * screen->width ();
4883
x = MOD (x, vWidth);
4884
x -= screen->vp ().x () * screen->width ();
4887
if (screen->vpSize ().height () != 1)
4889
y += screen->vp ().y () * screen->height ();
4890
y = MOD (y, vHeight);
4891
y -= screen->vp ().y () * screen->height ();
4894
tx = x - priv->attrib.x;
4895
ty = y - priv->attrib.y;
4904
if (priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask))
4907
if (priv->state & CompWindowStateStickyMask)
4913
if (screen->vpSize ().width ()!= 1)
4915
m = priv->attrib.x + tx;
4917
if (m - priv->output.left < (int) screen->width () - vWidth)
4919
else if (m + priv->width + priv->output.right > vWidth)
4923
if (screen->vpSize ().height () != 1)
4925
m = priv->attrib.y + ty;
4927
if (m - priv->output.top < (int) screen->height () - vHeight)
4929
else if (m + priv->height + priv->output.bottom > vHeight)
4933
if (priv->saveMask & CWX)
4934
priv->saveWc.x += wx;
4936
if (priv->saveMask & CWY)
4937
priv->saveWc.y += wy;
4947
CompWindow::startupId ()
4949
return priv->startupId;
4953
PrivateWindow::applyStartupProperties (CompStartupSequence *s)
4957
priv->initialViewport.setX (s->viewportX);
4958
priv->initialViewport.setY (s->viewportY);
4960
workspace = sn_startup_sequence_get_workspace (s->sequence);
4962
window->setDesktop (workspace);
4964
priv->initialTimestamp =
4965
sn_startup_sequence_get_timestamp (s->sequence);
4966
priv->initialTimestampSet = true;
4970
CompWindow::desktop ()
4972
return priv->desktop;
4976
CompWindow::clientLeader (bool checkAncestor)
4978
if (priv->clientLeader)
4979
return priv->clientLeader;
4982
return priv->getClientLeaderOfAncestor ();
4988
CompWindow::transientFor ()
4990
return priv->transientFor;
4994
CompWindow::pendingUnmaps ()
4996
return priv->pendingUnmaps;
5000
CompWindow::minimized ()
5002
WRAPABLE_HND_FUNC_RETURN (15, bool, minimized);
5003
return priv->minimized;
5007
CompWindow::placed ()
5009
return priv->placed;
5013
CompWindow::shaded ()
5015
return priv->shaded;
5019
CompWindow::border () const
5021
return priv->border;
5025
CompWindow::input () const
5031
CompWindow::output () const
5033
return priv->output;
5037
CompWindow::sizeHints () const
5039
return priv->sizeHints;
5043
PrivateWindow::updateMwmHints ()
5045
screen->priv->getMwmHints (priv->id, &priv->mwmFunc, &priv->mwmDecor);
5046
window->recalcActions ();
5050
PrivateWindow::updateStartupId ()
5052
char *oldId = startupId;
5055
startupId = getStartupId ();
5059
if (strcmp (startupId, oldId) == 0)
5065
if (managed && startupId && newId)
5072
initialTimestampSet = false;
5073
screen->priv->applyStartupProperties (window);
5075
if (initialTimestampSet)
5076
timestamp = initialTimestamp;
5078
/* as the viewport can't be transmitted via startup
5079
notification, assume the client changing the ID
5080
wanted to activate the window on the current viewport */
5082
vp = window->defaultViewport ();
5083
svp = screen->vp ();
5086
x = window->geometry ().x () + (svp.x () - vp.x ()) * size.width ();
5087
y = window->geometry ().y () + (svp.y () - vp.y ()) * size.height ();
5088
window->moveToViewportPosition (x, y, true);
5090
if (allowWindowFocus (0, timestamp))
5091
window->activate ();
5096
CompWindow::destroyed ()
5098
return priv->destroyed;
5102
CompWindow::invisible ()
5104
return priv->invisible;
5108
CompWindow::syncAlarm ()
5110
return priv->syncAlarm;
5113
CompWindow::CompWindow (Window aboveId,
5114
XWindowAttributes &wa,
5115
PrivateWindow *priv) :
5116
PluginClassStorage (windowPluginClassIndices),
5119
// TODO: Reparent first!
5121
priv->window = this;
5123
screen->insertWindow (this, aboveId);
5126
priv->serverGeometry.set (priv->attrib.x, priv->attrib.y,
5127
priv->attrib.width, priv->attrib.height,
5128
priv->attrib.border_width);
5129
priv->syncGeometry.set (priv->attrib.x, priv->attrib.y,
5130
priv->attrib.width, priv->attrib.height,
5131
priv->attrib.border_width);
5132
priv->geometry.set (priv->attrib.x, priv->attrib.y,
5133
priv->attrib.width, priv->attrib.height,
5134
priv->attrib.border_width);
5136
priv->width = priv->attrib.width + priv->attrib.border_width * 2;
5137
priv->height = priv->attrib.height + priv->attrib.border_width * 2;
5139
priv->sizeHints.flags = 0;
5141
priv->recalcNormalHints ();
5143
priv->transientFor = None;
5144
priv->clientLeader = None;
5146
XSelectInput (screen->dpy (), priv->id,
5147
PropertyChangeMask |
5151
priv->alpha = (priv->attrib.depth == 32);
5152
priv->lastPong = screen->priv->lastPing;
5154
if (screen->XShape ())
5155
XShapeSelectInput (screen->dpy (), priv->id, ShapeNotifyMask);
5157
if (priv->attrib.c_class != InputOnly)
5159
priv->region = CompRegion (priv->attrib.x, priv->attrib.y,
5160
priv->width, priv->height);
5161
priv->inputRegion = priv->region;
5163
/* need to check for DisplayModal state on all windows */
5164
priv->state = screen->priv->getWindowState (priv->id);
5166
priv->updateClassHints ();
5170
priv->attrib.map_state = IsUnmapped;
5173
priv->wmType = screen->priv->getWindowType (priv->id);
5174
priv->protocols = screen->priv->getProtocols (priv->id);
5176
if (!overrideRedirect ())
5178
priv->updateNormalHints ();
5180
priv->updateWmHints ();
5181
priv->updateTransientHint ();
5183
priv->clientLeader = priv->getClientLeader ();
5184
priv->startupId = priv->getStartupId ();
5188
screen->priv->getMwmHints (priv->id, &priv->mwmFunc, &priv->mwmDecor);
5190
if (!(priv->type & (CompWindowTypeDesktopMask | CompWindowTypeDockMask)))
5192
priv->desktop = screen->getWindowProp (priv->id, Atoms::winDesktop,
5194
if (priv->desktop != 0xffffffff)
5196
if (priv->desktop >= screen->nDesktop ())
5197
priv->desktop = screen->currentDesktop ();
5206
if (priv->attrib.map_state == IsViewable)
5208
priv->placed = true;
5210
if (!overrideRedirect ())
5212
// needs to happen right after maprequest
5215
priv->managed = true;
5217
if (screen->priv->getWmState (priv->id) == IconicState)
5219
if (priv->state & CompWindowStateShadedMask)
5220
priv->shaded = true;
5222
priv->minimized = true;
5226
if (priv->wmType & (CompWindowTypeDockMask |
5227
CompWindowTypeDesktopMask))
5229
setDesktop (0xffffffff);
5233
if (priv->desktop != 0xffffffff)
5234
priv->desktop = screen->currentDesktop ();
5236
screen->setWindowProp (priv->id, Atoms::winDesktop,
5242
priv->attrib.map_state = IsUnmapped;
5243
priv->pendingMaps++;
5247
updateAttributes (CompStackingUpdateModeNormal);
5249
if (priv->minimized || priv->inShowDesktopMode ||
5250
priv->hidden || priv->shaded)
5252
priv->state |= CompWindowStateHiddenMask;
5254
priv->pendingUnmaps++;
5256
if (priv->frame && !priv->shaded)
5257
XUnmapWindow (screen->dpy (), priv->frame);
5259
XUnmapWindow (screen->dpy (), priv->id);
5261
screen->priv->setWindowState (priv->state, priv->id);
5264
else if (!overrideRedirect ())
5266
if (screen->priv->getWmState (priv->id) == IconicState ||
5267
(priv->hints && priv->hints->initial_state == IconicState))
5269
// before everything else in maprequest
5273
/* Not managed until map processing is done here
5274
* since to go from Withdrawn -> Iconic the client
5275
* needs to map the window again */
5276
priv->managed = false;
5277
priv->placed = !(priv->hints && priv->hints->initial_state == IconicState);
5280
/* FIXME: CompWindowStateShadedMask can't be set
5281
* at this time anyways, so any window that wants
5282
* to start out shaded will have to be minimized instead */
5283
if (priv->state & CompWindowStateShadedMask)
5284
priv->shaded = true;
5286
priv->minimized = true;
5290
/* TODO: bailout properly when objectInitPlugins fails */
5291
assert (CompPlugin::windowInitPlugins (this));
5294
priv->updateIconGeometry ();
5297
resize (priv->attrib.x, priv->attrib.y,
5298
priv->attrib.width, ++priv->attrib.height - 1,
5299
priv->attrib.border_width);
5301
if (priv->attrib.map_state == IsViewable)
5303
priv->invisible = WINDOW_INVISIBLE (priv);
5308
CoreWindow::manage (Window aboveId, XWindowAttributes &wa)
5310
return new CompWindow (aboveId, wa, priv);
5313
CoreWindow::CoreWindow (Window id)
5315
priv = new PrivateWindow ();
5320
CompWindow::~CompWindow ()
5322
screen->unhookWindow (this);
5324
if (!priv->destroyed)
5328
priv->unreparent ();
5331
/* restore saved geometry and map if hidden */
5332
if (!priv->attrib.override_redirect)
5335
XConfigureWindow (screen->dpy (), priv->id,
5336
priv->saveMask, &priv->saveWc);
5340
if (priv->state & CompWindowStateHiddenMask)
5341
XMapWindow (screen->dpy (), priv->id);
5345
if (screen->XShape ())
5346
XShapeSelectInput (screen->dpy (), priv->id, NoEventMask);
5348
if (priv->id != screen->priv->grabWindow)
5349
XSelectInput (screen->dpy (), priv->id, NoEventMask);
5351
XUngrabButton (screen->dpy (), AnyButton, AnyModifier, priv->id);
5354
if (priv->attrib.map_state == IsViewable)
5356
if (priv->type == CompWindowTypeDesktopMask)
5357
screen->priv->desktopWindowCount--;
5359
if (priv->destroyed && priv->struts)
5360
screen->updateWorkarea ();
5363
if (priv->destroyed)
5364
screen->priv->updateClientList ();
5366
CompPlugin::windowFiniPlugins (this);
5371
PrivateWindow::PrivateWindow () :
5379
transientFor (None),
5380
clientLeader (None),
5388
type (CompWindowTypeUnknownMask),
5392
mwmDecor (MwmDecorAll),
5393
mwmFunc (MwmFuncAll),
5401
initialViewport (0, 0),
5403
initialTimestamp (0),
5404
initialTimestampSet (false),
5406
fullscreenMonitorsSet (false),
5410
inShowDesktopMode (false),
5440
closeRequests (false),
5441
lastCloseRequestTime (0)
5458
syncWaitTimer.setTimes (1000, 1200);
5459
syncWaitTimer.setCallback (boost::bind (&PrivateWindow::handleSyncAlarm,
5463
PrivateWindow::~PrivateWindow ()
5466
XSyncDestroyAlarm (screen->dpy (), syncAlarm);
5468
syncWaitTimer.stop ();
5471
XDestroyWindow (screen->dpy (), frame);
5493
CompWindow::syncWait ()
5495
return priv->syncWait;
5499
CompWindow::alpha ()
5501
WRAPABLE_HND_FUNC_RETURN (16, bool, alpha);
5507
CompWindow::overrideRedirect ()
5509
return priv->attrib.override_redirect;
5513
PrivateWindow::setOverrideRedirect (bool overrideRedirect)
5515
if (overrideRedirect == window->overrideRedirect ())
5518
priv->attrib.override_redirect = overrideRedirect ? 1 : 0;
5519
window->recalcType ();
5520
window->recalcActions ();
5522
screen->matchPropertyChanged (window);
5526
CompWindow::isMapped () const
5528
return priv->mapNum > 0;
5532
CompWindow::isViewable () const
5534
return (priv->attrib.map_state == IsViewable);
5538
CompWindow::isFocussable ()
5540
WRAPABLE_HND_FUNC_RETURN (17, bool, isFocussable);
5542
if (priv->inputHint)
5545
if (priv->protocols & CompWindowProtocolTakeFocusMask)
5552
CompWindow::windowClass ()
5554
return priv->attrib.c_class;
5558
CompWindow::depth ()
5560
return priv->attrib.depth;
5564
CompWindow::alive ()
5570
CompWindow::mwmDecor ()
5572
return priv->mwmDecor;
5576
CompWindow::mwmFunc ()
5578
return priv->mwmFunc;
5581
/* TODO: This function should be able to check the XShape event
5582
* kind and only get/set shape rectangles for either ShapeInput
5583
* or ShapeBounding, but not both at the same time
5587
CompWindow::updateFrameRegion ()
5589
if (priv->frame && priv->serverGeometry.width () == priv->geometry.width () &&
5590
priv->serverGeometry.height () == priv->geometry.height ())
5595
priv->frameRegion = CompRegion ();
5597
updateFrameRegion (priv->frameRegion);
5601
r = priv->region.boundingRect ();
5602
priv->frameRegion -= r;
5604
r.setGeometry (r.x1 () - priv->input.left,
5605
r.y1 () - priv->input.top,
5606
r.width () + priv->input.right + priv->input.left,
5607
r.height () + priv->input.bottom + priv->input.top);
5609
priv->frameRegion &= CompRegion (r);
5612
x = priv->geometry.x () - priv->input.left;
5613
y = priv->geometry.y () - priv->input.top;
5615
XShapeCombineRegion (screen->dpy (), priv->frame,
5616
ShapeBounding, -x, -y,
5617
priv->frameRegion.united (priv->region).handle (),
5620
XShapeCombineRegion (screen->dpy (), priv->frame,
5622
priv->frameRegion.united (priv->inputRegion).handle (),
5628
CompWindow::setWindowFrameExtents (CompWindowExtents *b,
5629
CompWindowExtents *i)
5631
/* Input extents are used for frame size,
5632
* Border extents used for placement.
5638
if (priv->input.left != i->left ||
5639
priv->input.right != i->right ||
5640
priv->input.top != i->top ||
5641
priv->input.bottom != i->bottom)
5643
unsigned long data[4];
5650
/* Use b for _NET_WM_FRAME_EXTENTS here because
5651
* that is the representation of the actual decoration
5652
* around the window that the user sees and should
5653
* be used for placement and such */
5658
data[3] = b->bottom;
5660
XChangeProperty (screen->dpy (), priv->id,
5661
Atoms::frameExtents,
5662
XA_CARDINAL, 32, PropModeReplace,
5663
(unsigned char *) data, 4);
5664
priv->updateSize ();
5665
priv->updateFrameWindow ();
5670
CompWindow::hasUnmapReference ()
5672
return (priv && priv->unmapRefCnt > 1);
5676
CompWindow::updateFrameRegion (CompRegion& region)
5677
WRAPABLE_HND_FUNC (12, updateFrameRegion, region)
5680
PrivateWindow::reparent ()
5682
XSetWindowAttributes attr;
5683
XWindowAttributes wa;
5686
unsigned int nchildren;
5687
Window *children, root_return, parent_return;
5688
CompWindow::Geometry &sg = serverGeometry;
5689
Display *dpy = screen->dpy ();
5690
Visual *visual = DefaultVisual (screen->dpy (),
5691
screen->screenNum ());
5692
Colormap cmap = DefaultColormap (screen->dpy (),
5693
screen->screenNum ());
5694
bool success = false;
5696
if (frame || attrib.override_redirect)
5702
/* Don't ever reparent windows which have ended up
5703
* reparented themselves on the server side but not
5704
* on the client side */
5706
success = XQueryTree (dpy, id, &root_return,
5707
&parent_return, &children, &nchildren);
5709
if (success && parent_return != root_return)
5715
if (success && !XGetWindowAttributes (dpy, id, &wa))
5723
XUngrabServer (dpy);
5730
XChangeSaveSet (dpy, id, SetModeInsert);
5731
XSelectInput (dpy, id, NoEventMask);
5732
XSelectInput (dpy, screen->root (), NoEventMask);
5734
xwc.border_width = 0;
5735
XConfigureWindow (dpy, id, CWBorderWidth, &xwc);
5737
mask = CWBorderPixel | CWColormap | CWBackPixmap;
5739
if (attrib.depth == 32)
5741
cmap = attrib.colormap;
5742
visual = attrib.visual;
5745
attr.background_pixmap = None;
5746
attr.border_pixel = 0;
5747
attr.colormap = cmap;
5749
frame = XCreateWindow (dpy, screen->root (), 0, 0,
5750
sg.width (), sg.height (), 0, attrib.depth,
5751
InputOutput, visual, mask, &attr);
5753
wrapper = XCreateWindow (dpy, frame, 0, 0,
5754
sg.width (), sg.height (), 0, attrib.depth,
5755
InputOutput, visual, mask, &attr);
5757
xwc.stack_mode = Below;
5760
/* Make sure the frame is underneath the client */
5761
XConfigureWindow (dpy, frame, CWSibling | CWStackMode, &xwc);
5763
/* Wait for the restacking to finish */
5766
/* Always need to have the wrapper window mapped */
5767
XMapWindow (dpy, wrapper);
5769
/* Reparent the client into the wrapper window */
5770
XReparentWindow (dpy, id, wrapper, 0, 0);
5772
attr.event_mask = PropertyChangeMask | FocusChangeMask |
5773
EnterWindowMask | LeaveWindowMask;
5775
/* We don't care about client events on the frame, and listening for them
5776
* will probably end up fighting the client anyways, so disable them */
5778
attr.do_not_propagate_mask = KeyPressMask | KeyReleaseMask |
5779
ButtonPressMask | ButtonReleaseMask |
5780
EnterWindowMask | LeaveWindowMask |
5781
PointerMotionMask | PointerMotionHintMask |
5782
Button1MotionMask | Button2MotionMask |
5783
Button3MotionMask | Button4MotionMask |
5784
Button5MotionMask | ButtonMotionMask |
5785
KeymapStateMask | ExposureMask |
5786
VisibilityChangeMask | StructureNotifyMask |
5787
ResizeRedirectMask | SubstructureNotifyMask |
5788
SubstructureRedirectMask | FocusChangeMask |
5789
PropertyChangeMask | ColormapChangeMask |
5790
OwnerGrabButtonMask;
5792
XChangeWindowAttributes (dpy, id, CWEventMask | CWDontPropagate, &attr);
5794
if (wa.map_state == IsViewable || shaded)
5795
XMapWindow (dpy, frame);
5797
attr.event_mask = SubstructureRedirectMask | StructureNotifyMask |
5798
SubstructureNotifyMask | EnterWindowMask |
5801
XChangeWindowAttributes (dpy, frame, CWEventMask, &attr);
5802
XChangeWindowAttributes (dpy, wrapper, CWEventMask, &attr);
5804
XSelectInput (dpy, screen->root (),
5805
SubstructureRedirectMask |
5806
SubstructureNotifyMask |
5807
StructureNotifyMask |
5808
PropertyChangeMask |
5818
XUngrabServer (dpy);
5821
XMoveResizeWindow (dpy, frame, sg.x (), sg.y (), sg.width (), sg.height ());
5823
updatePassiveButtonGrabs ();
5825
window->windowNotify (CompWindowNotifyReparent);
5831
PrivateWindow::unreparent ()
5833
Display *dpy = screen->dpy ();
5843
if (XCheckTypedWindowEvent (dpy, id, DestroyNotify, &e))
5845
XPutBackEvent (dpy, &e);
5849
if ((!destroyed) && alive)
5853
XChangeSaveSet (dpy, id, SetModeDelete);
5854
XSelectInput (dpy, frame, NoEventMask);
5855
XSelectInput (dpy, wrapper, NoEventMask);
5856
XSelectInput (dpy, id, NoEventMask);
5857
XSelectInput (dpy, screen->root (), NoEventMask);
5858
XReparentWindow (dpy, id, screen->root (), 0, 0);
5860
/* Wait for the reparent to finish */
5863
xwc.stack_mode = Below;
5864
xwc.sibling = frame;
5865
XConfigureWindow (dpy, id, CWSibling | CWStackMode, &xwc);
5867
/* Wait for the window to be restacked */
5870
XUnmapWindow (dpy, frame);
5872
XSelectInput (dpy, id, PropertyChangeMask | EnterWindowMask |
5875
XSelectInput (dpy, screen->root (),
5876
SubstructureRedirectMask |
5877
SubstructureNotifyMask |
5878
StructureNotifyMask |
5879
PropertyChangeMask |
5889
XUngrabServer (dpy);
5892
XMoveWindow (dpy, id, serverGeometry.x (), serverGeometry.y ());
5895
XDestroyWindow (dpy, wrapper);
5896
XDestroyWindow (dpy, frame);
5900
window->windowNotify (CompWindowNotifyUnreparent);