| 72 |
@@ -72,6 +72,10 @@ |
| 72 |
{
|
| 73 |
// Construct the client
|
| 74 |
PScreen::instance()->grabServer();
|
| 75 |
if (! validate() || ! getAndUpdateWindowAttributes()) {
|
| 76 |
PScreen::instance()->ungrabServer(true);
|
| 77 |
return;
|
| 78 |
}
|
| 79 |
|
| 80 |
// PWinObj attributes
|
| 81 |
_window = new_client;
|
| ... |
|
| 86 |
@@ -82,42 +86,6 @@ |
| 86 |
_title.setId(_id);
|
| 87 |
_title.infoAdd(PDecor::TitleItem::INFO_ID);
|
| 88 |
|
| 85 |
if (! validate()) {
|
| 86 |
#ifdef DEBUG
|
| 87 |
cerr << __FILE__ << "@" << __LINE__ << ": " << "Couldn't validate client." << endl;
|
| 88 |
#endif // DEBUG
|
| 89 |
PScreen::instance()->ungrabServer(true);
|
| 90 |
return;
|
| 91 |
}
|
| 92 |
|
| 93 |
XWindowAttributes attr;
|
| 94 |
if (! XGetWindowAttributes(_dpy, _window, &attr)) {
|
| 95 |
#ifdef DEBUG
|
| 96 |
cerr << __FILE__ << "@" << __LINE__ << ": " << "Client died." << endl;
|
| 97 |
#endif // DEBUG
|
| 98 |
PScreen::instance()->ungrabServer(true);
|
| 99 |
return;
|
| 100 |
}
|
| 101 |
_gm.x = attr.x;
|
| 102 |
_gm.y = attr.y;
|
| 103 |
_gm.width = attr.width;
|
| 104 |
_gm.height = attr.height;
|
| 105 |
|
| 106 |
_cmap = attr.colormap;
|
| 107 |
_size = XAllocSizeHints();
|
| 108 |
|
| 109 |
// get trans window and the window attributes
|
| 110 |
getTransientForHint();
|
| 111 |
|
| 112 |
XSetWindowAttributes sattr;
|
| 113 |
sattr.event_mask =
|
| 114 |
PropertyChangeMask|StructureNotifyMask|FocusChangeMask;
|
| 115 |
sattr.do_not_propagate_mask =
|
| 116 |
ButtonPressMask|ButtonReleaseMask|ButtonMotionMask;
|
| 117 |
|
| 118 |
// We don't want these masks to be propagated down to the frame
|
| 119 |
XChangeWindowAttributes(_dpy, _window, CWEventMask|CWDontPropagate, &sattr);
|
| 120 |
|
| 125 |
#ifdef HAVE_SHAPE
|
| 126 |
if (PScreen::instance()->hasExtensionShape()) {
|
| 127 |
XShapeSelectInput(_dpy, _window, ShapeNotifyMask);
|
| ... |
|
| 111 |
@@ -143,144 +111,20 @@ |
| 111 |
AutoProperty *ap = readAutoprops(WindowManager::instance()->isStartup()
|
| 112 |
? APPLY_ON_NEW : APPLY_ON_START);
|
| 113 |
|
| 146 |
readMwmHints(); // read atoms
|
| 147 |
readEwmhHints();
|
| 148 |
readPekwmHints();
|
| 149 |
readIcon();
|
| 150 |
readClientPid();
|
| 151 |
readClientRemote();
|
| 152 |
getWMProtocols();
|
| 153 |
|
| 154 |
ulong initial_state = NormalState;
|
| 155 |
XWMHints* hints = XGetWMHints(_dpy, _window);
|
| 156 |
if (hints) {
|
| 157 |
// get the input focus mode
|
| 158 |
if (hints->flags&InputHint) { // FIXME: More logic needed
|
| 159 |
_wm_hints_input = hints->input;
|
| 160 |
}
|
| 129 |
readHints();
|
| 130 |
findOrCreateFrame(ap);
|
| 131 |
setInitialState();
|
| 132 |
|
| 165 |
// Get initial state of the window
|
| 166 |
if (hints->flags&StateHint) {
|
| 167 |
initial_state = hints->initial_state;
|
| 168 |
}
|
| 169 |
|
| 170 |
XFree(hints);
|
| 171 |
}
|
| 172 |
|
| 173 |
// Set state either specified in hint
|
| 174 |
if (getWmState() == IconicState) {
|
| 175 |
_iconified = true;
|
| 176 |
}
|
| 177 |
|
| 178 |
if (_iconified || initial_state == IconicState) {
|
| 179 |
_iconified = true;
|
| 180 |
_mapped = true;
|
| 181 |
unmapWindow();
|
| 182 |
} else {
|
| 183 |
setWmState(initial_state);
|
| 184 |
}
|
| 185 |
|
| 186 |
// grab keybindings and mousebutton actions
|
| 155 |
// Grab keybindings and mousebutton actions
|
| 156 |
KeyGrabber::instance()->grabKeys(_window);
|
| 157 |
grabButtons();
|
| 158 |
|
| 191 |
// don't want to spread the giveInputFocuses
|
| 192 |
bool do_focus = is_new ? Config::instance()->isFocusNew() : false;
|
| 193 |
bool do_autogroup = true;
|
| 194 |
bool is_active = getPekwmFrameActive();
|
| 195 |
|
| 196 |
// If pekwm is already running, check against autoproperty then
|
| 197 |
// tagged frame. If starting up, check if it has a FRAME_ID and if not
|
| 198 |
// use autoproperties.
|
| 199 |
if (WindowManager::instance()->isStartup()) {
|
| 200 |
// Check for tagged frame
|
| 201 |
Frame *frame = Frame::getTagFrame();
|
| 202 |
if (frame && frame->isMapped()) {
|
| 203 |
_parent = frame;
|
| 204 |
frame->addChild(this);
|
| 205 |
|
| 206 |
if (! Frame::getTagBehind()) {
|
| 207 |
frame->activateChild(this);
|
| 208 |
do_focus = frame->isFocused();
|
| 209 |
}
|
| 210 |
}
|
| 211 |
|
| 212 |
// Not startup, pekwm (re)start it is.
|
| 213 |
} else {
|
| 214 |
long id;
|
| 215 |
if (AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ID), id)) {
|
| 216 |
do_autogroup = false;
|
| 217 |
_parent = Frame::findFrameFromID(id);
|
| 218 |
if (_parent) {
|
| 219 |
Frame *frame = static_cast<Frame*>(_parent);
|
| 220 |
frame->addChildOrdered(this);
|
| 221 |
if (is_active) {
|
| 222 |
frame->activateChild(this);
|
| 223 |
}
|
| 224 |
do_focus = frame->isFocused();
|
| 225 |
}
|
| 226 |
}
|
| 227 |
}
|
| 228 |
|
| 229 |
|
| 230 |
// Apply Autoproperties again to override EWMH state. It's done twice as
|
| 231 |
// we need the cfg_deny property when reading the EWMH state.
|
| 232 |
if (ap) {
|
| 233 |
applyAutoprops(ap);
|
| 234 |
|
| 235 |
if (do_autogroup && ! _parent && (ap->group_size >= 0)) {
|
| 236 |
Frame* frame = WindowManager::instance()->findGroup(ap);
|
| 237 |
if (frame) {
|
| 238 |
frame->addChild(this);
|
| 239 |
|
| 240 |
if (! ap->group_behind) {
|
| 241 |
frame->activateChild(this);
|
| 242 |
do_focus = frame->isFocused();
|
| 243 |
}
|
| 244 |
if (ap->group_raise) {
|
| 245 |
frame->raise();
|
| 246 |
}
|
| 247 |
}
|
| 248 |
}
|
| 249 |
}
|
| 250 |
|
| 219 |
// Tell the world about our state
|
| 220 |
updateEwmhStates();
|
| 221 |
|
| 222 |
PScreen::instance()->ungrabServer(true);
|
| 223 |
|
| 256 |
// if we don't have a frame already, create a new one
|
| 257 |
if (! _parent) {
|
| 258 |
_parent = new Frame(this, ap);
|
| 259 |
}
|
| 260 |
|
| 261 |
// Make sure the window is mapped, this is done after it has been
|
| 262 |
// added to the decor/frame as otherwise IsViewable state won't
|
| 263 |
// be correct and we don't know whether or not to place the window
|
| 264 |
if (! _iconified) {
|
| 265 |
PWinObj::mapWindow();
|
| 266 |
}
|
| 267 |
|
| 268 |
// Let us hear what autoproperties has to say about focusing
|
| 269 |
if (is_new && ap && ap->isMask(AP_FOCUS_NEW)) {
|
| 270 |
do_focus = ap->focus_new;
|
| 271 |
}
|
| 272 |
|
| 273 |
// Only can give input focus to mapped windows
|
| 274 |
if (_parent->isMapped()) {
|
| 275 |
// Ordinary focus
|
| 276 |
if (do_focus) {
|
| 277 |
_parent->giveInputFocus();
|
| 278 |
|
| 279 |
// Check if we are transient, and if we want to focus
|
| 280 |
} else if ((_transient != None)
|
| 281 |
&& Config::instance()->isFocusNewChild()) {
|
| 282 |
Client *trans_for = findClientFromWindow(_transient);
|
| 283 |
if (trans_for && trans_for->isFocused()) {
|
| 284 |
_parent->giveInputFocus();
|
| 285 |
}
|
| 286 |
}
|
| 287 |
}
|
| 256 |
setMappedStateAndFocus(is_new, ap);
|
| 257 |
|
| 258 |
_alive = true;
|
| 259 |
|
| ... |
|
| 206 |
@@ -362,6 +206,198 @@ |
| 206 |
PScreen::instance()->ungrabServer(true);
|
| 207 |
}
|
| 208 |
|
| 209 |
/**
|
| 210 |
* Read basic window attributes including geometry and update the
|
| 211 |
* window attributes being listened to. Returns false if the client
|
| 212 |
* disappears during the check.
|
| 213 |
*/
|
| 214 |
bool
|
| 215 |
Client::getAndUpdateWindowAttributes(void)
|
| 216 |
{
|
| 217 |
XWindowAttributes attr;
|
| 218 |
if (! XGetWindowAttributes(_dpy, _window, &attr)) {
|
| 219 |
return false;
|
| 220 |
}
|
| 221 |
_gm.x = attr.x;
|
| 222 |
_gm.y = attr.y;
|
| 223 |
_gm.width = attr.width;
|
| 224 |
_gm.height = attr.height;
|
| 225 |
|
| 226 |
_cmap = attr.colormap;
|
| 227 |
_size = XAllocSizeHints();
|
| 228 |
|
| 229 |
XSetWindowAttributes sattr;
|
| 230 |
sattr.event_mask =
|
| 231 |
PropertyChangeMask|StructureNotifyMask|FocusChangeMask;
|
| 232 |
sattr.do_not_propagate_mask =
|
| 233 |
ButtonPressMask|ButtonReleaseMask|ButtonMotionMask;
|
| 234 |
|
| 235 |
// We don't want these masks to be propagated down to the frame
|
| 236 |
XChangeWindowAttributes(_dpy, _window, CWEventMask|CWDontPropagate, &sattr);
|
| 237 |
|
| 238 |
return true;
|
| 239 |
}
|
| 240 |
|
| 241 |
/**
|
| 242 |
* Find frame for client based on tagging, hints and
|
| 243 |
* autoproperties. Create a new one if not found and add the client.
|
| 244 |
*/
|
| 245 |
void
|
| 246 |
Client::findOrCreateFrame(AutoProperty *autoproperty)
|
| 247 |
{
|
| 248 |
if (! _parent) {
|
| 249 |
findTaggedFrame();
|
| 250 |
}
|
| 251 |
if (! _parent) {
|
| 252 |
findPreviousFrame();
|
| 253 |
}
|
| 254 |
|
| 255 |
// Apply Autoproperties again to override EWMH state. It's done twice as
|
| 256 |
// we need the cfg_deny property when reading the EWMH state.
|
| 257 |
if (autoproperty != 0) {
|
| 258 |
applyAutoprops(autoproperty);
|
| 259 |
if (! _parent) {
|
| 260 |
findAutoGroupFrame(autoproperty);
|
| 261 |
}
|
| 262 |
}
|
| 263 |
|
| 264 |
// if we don't have a frame already, create a new one
|
| 265 |
if (! _parent) {
|
| 266 |
_parent = new Frame(this, autoproperty);
|
| 267 |
}
|
| 268 |
}
|
| 269 |
|
| 270 |
/**
|
| 271 |
* Find from client from for the currently tagged client.
|
| 272 |
*/
|
| 273 |
bool
|
| 274 |
Client::findTaggedFrame(void)
|
| 275 |
{
|
| 276 |
if (! WindowManager::instance()->isStartup()) {
|
| 277 |
return false;
|
| 278 |
}
|
| 279 |
|
| 280 |
// Check for tagged frame
|
| 281 |
Frame *frame = Frame::getTagFrame();
|
| 282 |
if (frame && frame->isMapped()) {
|
| 283 |
_parent = frame;
|
| 284 |
frame->addChild(this);
|
| 285 |
|
| 286 |
if (! Frame::getTagBehind()) {
|
| 287 |
frame->activateChild(this);
|
| 288 |
}
|
| 289 |
}
|
| 290 |
|
| 291 |
return _parent != 0;
|
| 292 |
}
|
| 293 |
|
| 294 |
/**
|
| 295 |
* Find frame for client on PEKWM_FRAME_ID hint.
|
| 296 |
*/
|
| 297 |
bool
|
| 298 |
Client::findPreviousFrame(void)
|
| 299 |
{
|
| 300 |
if (WindowManager::instance()->isStartup()) {
|
| 301 |
return false;
|
| 302 |
}
|
| 303 |
|
| 304 |
long id;
|
| 305 |
if (! AtomUtil::getLong(_window, Atoms::getAtom(PEKWM_FRAME_ID), id)) {
|
| 306 |
_parent = Frame::findFrameFromID(id);
|
| 307 |
if (_parent) {
|
| 308 |
Frame *frame = static_cast<Frame*>(_parent);
|
| 309 |
frame->addChildOrdered(this);
|
| 310 |
if (getPekwmFrameActive()) {
|
| 311 |
frame->activateChild(this);
|
| 312 |
}
|
| 313 |
}
|
| 314 |
}
|
| 315 |
|
| 316 |
return _parent != 0;
|
| 317 |
}
|
| 318 |
|
| 319 |
/**
|
| 320 |
* Find frame for client based on autoproperties.
|
| 321 |
*/
|
| 322 |
bool
|
| 323 |
Client::findAutoGroupFrame(AutoProperty *autoproperty)
|
| 324 |
{
|
| 325 |
if (autoproperty->group_size < 0) {
|
| 326 |
return false;
|
| 327 |
}
|
| 328 |
|
| 329 |
Frame* frame = WindowManager::instance()->findGroup(autoproperty);
|
| 330 |
if (frame) {
|
| 331 |
frame->addChild(this);
|
| 332 |
|
| 333 |
if (! autoproperty->group_behind) {
|
| 334 |
frame->activateChild(this);
|
| 335 |
}
|
| 336 |
if (autoproperty->group_raise) {
|
| 337 |
frame->raise();
|
| 338 |
}
|
| 339 |
}
|
| 340 |
|
| 341 |
return _parent != 0;
|
| 342 |
}
|
| 343 |
|
| 344 |
/**
|
| 345 |
* Get the client state and set iconified and mapped flags.
|
| 346 |
*/
|
| 347 |
void
|
| 348 |
Client::setInitialState(void)
|
| 349 |
{
|
| 350 |
// Set state either specified in hint
|
| 351 |
ulong initial_state = readWmHints();
|
| 352 |
if (getWmState() == IconicState) {
|
| 353 |
_iconified = true;
|
| 354 |
}
|
| 355 |
|
| 356 |
if (_iconified || initial_state == IconicState) {
|
| 357 |
_iconified = true;
|
| 358 |
_mapped = true;
|
| 359 |
unmapWindow();
|
| 360 |
} else {
|
| 361 |
setWmState(initial_state);
|
| 362 |
}
|
| 363 |
}
|
| 364 |
|
| 365 |
/**
|
| 366 |
* Ensure the Client is (un) mapped and give input focus if requested.
|
| 367 |
*/
|
| 368 |
void
|
| 369 |
Client::setMappedStateAndFocus(bool is_new, AutoProperty *autoproperty)
|
| 370 |
{
|
| 371 |
// Make sure the window is mapped, this is done after it has been
|
| 372 |
// added to the decor/frame as otherwise IsViewable state won't
|
| 373 |
// be correct and we don't know whether or not to place the window
|
| 374 |
if (! _iconified) {
|
| 375 |
PWinObj::mapWindow();
|
| 376 |
}
|
| 377 |
|
| 378 |
// Let us hear what autoproperties has to say about focusing
|
| 379 |
bool do_focus = is_new ? Config::instance()->isFocusNew() : false;
|
| 380 |
if (is_new && autoproperty && autoproperty->isMask(AP_FOCUS_NEW)) {
|
| 381 |
do_focus = autoproperty->focus_new;
|
| 382 |
}
|
| 383 |
|
| 384 |
// Only can give input focus to mapped windows
|
| 385 |
if (_parent->isMapped()) {
|
| 386 |
// Ordinary focus
|
| 387 |
if (do_focus) {
|
| 388 |
_parent->giveInputFocus();
|
| 389 |
|
| 390 |
// Check if we are transient, and if we want to focus
|
| 391 |
} else if ((_transient != None)
|
| 392 |
&& Config::instance()->isFocusNewChild()) {
|
| 393 |
Client *trans_for = findClientFromWindow(_transient);
|
| 394 |
if (trans_for && trans_for->isFocused()) {
|
| 395 |
_parent->giveInputFocus();
|
| 396 |
}
|
| 397 |
}
|
| 398 |
}
|
| 399 |
}
|
| 400 |
|
| 401 |
// START - PWinObj interface.
|
| 402 |
|
| 403 |
//! @brief Maps the window.
|
| ... |
|
| 739 |
@@ -703,6 +739,46 @@ |
| 739 |
}
|
| 740 |
|
| 741 |
/**
|
| 742 |
* Read "all" hints required during creation of Client.
|
| 743 |
*/
|
| 744 |
void
|
| 745 |
Client::readHints(void)
|
| 746 |
{
|
| 747 |
getTransientForHint();
|
| 748 |
readMwmHints(); // read atoms
|
| 749 |
readEwmhHints();
|
| 750 |
readPekwmHints();
|
| 751 |
readIcon();
|
| 752 |
readClientPid();
|
| 753 |
readClientRemote();
|
| 754 |
getWMProtocols();
|
| 755 |
}
|
| 756 |
|
| 757 |
/**
|
| 758 |
* Read WM Hints, return the initial state of the window.
|
| 759 |
*/
|
| 760 |
ulong
|
| 761 |
Client::readWmHints(void)
|
| 762 |
{
|
| 763 |
ulong initial_state = NormalState;
|
| 764 |
XWMHints* hints = XGetWMHints(_dpy, _window);
|
| 765 |
if (hints) {
|
| 766 |
// get the input focus mode
|
| 767 |
if (hints->flags&InputHint) { // FIXME: More logic needed
|
| 768 |
_wm_hints_input = hints->input;
|
| 769 |
}
|
| 770 |
|
| 771 |
// Get initial state of the window
|
| 772 |
if (hints->flags&StateHint) {
|
| 773 |
initial_state = hints->initial_state;
|
| 774 |
}
|
| 775 |
|
| 776 |
XFree(hints);
|
| 777 |
}
|
| 778 |
return initial_state;
|
| 779 |
}
|
| 780 |
|
| 781 |
/**
|
| 782 |
* Read the WM_CLASS hint and set information on the _class_hint used
|
| 783 |
* in matching auto properties.
|
| 784 |
*/
|
| ... |
|