1 /*
2 * IceWM
3 *
4 * Copyright (C) 1997-2001 Marko Macek
5 */
6 #include "config.h"
7 #include "wmcontainer.h"
8 #include "wmframe.h"
9 #include "wmmgr.h"
10 #include "wmapp.h"
11 #include "prefs.h"
12
YClientContainer(YWindow * parent,YFrameWindow * frame,int depth,Visual * visual,Colormap cmap)13 YClientContainer::YClientContainer(YWindow *parent, YFrameWindow *frame,
14 int depth, Visual *visual, Colormap cmap)
15 : YWindow(parent, None, depth, visual, cmap)
16 {
17 fFrame = frame;
18 fHaveGrab = false;
19 fHaveActionGrab = false;
20
21 setStyle(wsManager | wsNoExpose);
22 setPointer(YWMApp::leftPointer);
23 setTitle("Container");
24 show();
25 }
26
~YClientContainer()27 YClientContainer::~YClientContainer() {
28 if (destroyed() == false)
29 releaseButtons();
30 }
31
handleButton(const XButtonEvent & button)32 void YClientContainer::handleButton(const XButtonEvent &button) {
33 if (clientMouseActions) {
34 unsigned int k = button.button + XK_Pointer_Button1 - 1;
35 unsigned int m = KEY_MODMASK(button.state);
36 unsigned int vm = VMod(m);
37
38 if (gMouseWinSize.eq(k, vm)) {
39 XAllowEvents(xapp->display(), AsyncPointer, CurrentTime);
40
41 int px = button.x + x();
42 int py = button.y + y();
43 int gx = (px * 3 / (int)width() - 1);
44 int gy = (py * 3 / (int)height() - 1);
45 if (gx < 0) gx = -1;
46 if (gx > 0) gx = 1;
47 if (gy < 0) gy = -1;
48 if (gy > 0) gy = 1;
49 bool doMove = (gx == 0 && gy == 0) ? true : false;
50 int mx, my;
51 if (doMove) {
52 mx = px;
53 my = py;
54 } else {
55 mx = button.x_root;
56 my = button.y_root;
57 }
58 if ((doMove && getFrame()->canMove()) ||
59 (!doMove && getFrame()->canSize()))
60 {
61 getFrame()->startMoveSize(doMove, true,
62 gx, gy,
63 mx, my);
64 }
65 return ;
66 }
67 else if (gMouseWinMove.eq(k, vm)) {
68 XAllowEvents(xapp->display(), AsyncPointer, CurrentTime);
69
70 if (getFrame()->canMove()) {
71 int px = button.x + x();
72 int py = button.y + y();
73 getFrame()->startMoveSize(true, true,
74 0, 0,
75 px, py);
76 }
77 return ;
78 }
79 else if (gMouseWinRaise.eq(k, vm)
80 && (gMouseWinRaise != gMouseWinLower || getFrame()->canRaise()))
81 {
82 XAllowEvents(xapp->display(), AsyncPointer, CurrentTime);
83 getFrame()->wmRaise();
84 return ;
85 }
86 else if (gMouseWinLower.eq(k, vm)) {
87 XAllowEvents(xapp->display(), AsyncPointer, CurrentTime);
88 getFrame()->wmLower();
89 return ;
90 }
91 }
92
93 bool doRaise = false;
94 bool doActivate = false;
95 bool firstClick = false;
96
97 if (!(button.state & ControlMask) &&
98 (buttonRaiseMask & (1 << (button.button - 1))) &&
99 (!useMouseWheel || (button.button != 4 && button.button != 5)))
100 {
101 if (focusOnClickClient) {
102 if (!getFrame()->isTypeDock()) {
103 doActivate = (getFrame() != manager->getFocus());
104 if (getFrame()->canFocusByMouse() && !getFrame()->focused())
105 firstClick = true;
106 }
107 }
108 if (raiseOnClickClient && getFrame()->canRaise()) {
109 doRaise = true;
110 firstClick = true;
111 }
112 }
113
114 ///!!! it might be nice if this was per-window option (app-request)
115 if (!firstClick || passFirstClickToClient)
116 XAllowEvents(xapp->display(), ReplayPointer, CurrentTime);
117 else
118 XAllowEvents(xapp->display(), AsyncPointer, CurrentTime);
119 xapp->sync();
120
121 ///!!! do this first?
122 if (doActivate)
123 getFrame()->focus();
124 if (doRaise && (!doActivate || !raiseOnFocus))
125 getFrame()->wmRaise();
126 }
127
128 // manage button grab on frame window to capture clicks to client window
129 // we want to keep the grab when:
130 // focusOnClickClient && not focused
131 // || raiseOnClickClient && not can be raised
132
133 // ('not on top' != 'can be raised')
134 // the difference is when we have transients and explicitFocus
135 // also there is the difference with layers and multiple workspaces
136
grabButtons()137 void YClientContainer::grabButtons() {
138 grabActions();
139 if (!fHaveGrab && (clickFocus ||
140 focusOnClickClient ||
141 raiseOnClickClient))
142 {
143 for (int button = Button1; button <= Button3; ++button) {
144 if (buttonRaiseMask & (1 << (button - Button1))) {
145 XGrabButton(xapp->display(), button, AnyModifier,
146 handle(), True, ButtonPressMask,
147 GrabModeSync, GrabModeAsync, None, None);
148 }
149 }
150 fHaveGrab = true;
151 }
152 }
153
releaseButtons()154 void YClientContainer::releaseButtons() {
155 if (fHaveGrab) {
156 fHaveGrab = false;
157 for (int button = Button1; button <= Button3; ++button) {
158 if (buttonRaiseMask & (1 << (button - Button1))) {
159 XUngrabButton(xapp->display(), button, AnyModifier, handle());
160 }
161 }
162 fHaveActionGrab = false;
163 }
164 grabActions();
165 }
166
regrabMouse()167 void YClientContainer::regrabMouse() {
168 fHaveActionGrab = false;
169 releaseButtons();
170 grabButtons();
171 }
172
grabActions()173 void YClientContainer::grabActions() {
174 if (clientMouseActions && fHaveActionGrab == false) {
175 WMKey grab[] = { gMouseWinMove, gMouseWinSize,
176 gMouseWinRaise, gMouseWinLower };
177 const int count = int ACOUNT(grab) - (gMouseWinRaise == gMouseWinLower);
178 for (int i = 0; i < count; ++i) {
179 int button = int(grab[i].key) - XK_Pointer_Button1 + Button1;
180 if (inrange(button, Button1, Button3)) {
181 grabVButton(button, grab[i].mod);
182 }
183 }
184 fHaveActionGrab = true;
185 }
186 }
187
handleConfigureRequest(const XConfigureRequestEvent & configureRequest)188 void YClientContainer::handleConfigureRequest(const XConfigureRequestEvent &configureRequest) {
189 MSG(("configure request in frame"));
190
191 if (getFrame() &&
192 configureRequest.window == getFrame()->client()->handle())
193 {
194 getFrame()->configureClient(configureRequest);
195 }
196 }
197
handleMapRequest(const XMapRequestEvent & mapRequest)198 void YClientContainer::handleMapRequest(const XMapRequestEvent &mapRequest) {
199 if (mapRequest.window == getFrame()->client()->handle()
200 && getFrame()->isPassive() == false)
201 {
202 if (getFrame()->isUnmapped()) {
203 manager->lockFocus();
204 getFrame()->makeMapped();
205 manager->unlockFocus();
206 }
207 bool doActivate = true;
208 getFrame()->updateFocusOnMap(doActivate);
209 if (doActivate) {
210 getFrame()->activateWindow(true);
211 }
212 }
213 }
214
handleCrossing(const XCrossingEvent & crossing)215 void YClientContainer::handleCrossing(const XCrossingEvent &crossing) {
216 if (getFrame() && pointerColormap) {
217 if (crossing.type == EnterNotify)
218 manager->setColormapWindow(getFrame());
219 else if (crossing.type == LeaveNotify &&
220 crossing.detail != NotifyInferior &&
221 crossing.mode == NotifyNormal &&
222 manager->colormapWindow() == getFrame())
223 {
224 manager->setColormapWindow(nullptr);
225 }
226 }
227 }
228
229
230 // vim: set sw=4 ts=4 et:
231