void Client::manage(Boolean mapped) { Boolean shouldHide, reshape; XWMHints *hints; Display *d = display(); long mSize; int state; XSelectInput(d, m_window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask); m_iconName = getProperty(XA_WM_ICON_NAME); m_name = getProperty(XA_WM_NAME); setLabel(); getColormaps(); getProtocols(); getTransient(); hints = XGetWMHints(d, m_window); if (!getState(&state)) { state = hints ? hints->initial_state : NormalState; } shouldHide = (state == IconicState); if (hints) XFree(hints); if (XGetWMNormalHints(d, m_window, &m_sizeHints, &mSize) == 0 || m_sizeHints.flags == 0) { m_sizeHints.flags = PSize; } m_fixedSize = False; // if ((m_sizeHints.flags & (USSize | PSize))) m_fixedSize = True; if ((m_sizeHints.flags & (PMinSize | PMaxSize)) == (PMinSize | PMaxSize) && (m_sizeHints.min_width == m_sizeHints.max_width && m_sizeHints.min_height == m_sizeHints.max_height)) m_fixedSize = True; reshape = !mapped; if (m_fixedSize) { if ((m_sizeHints.flags & USPosition)) reshape = False; if ((m_sizeHints.flags & PPosition) && shouldHide) reshape = False; if ((m_transient != None)) reshape = False; } if ((m_sizeHints.flags & PBaseSize)) { m_minWidth = m_sizeHints.base_width; m_minHeight = m_sizeHints.base_height; } else if ((m_sizeHints.flags & PMinSize)) { m_minWidth = m_sizeHints.min_width; m_minHeight = m_sizeHints.min_height; } else { m_minWidth = m_minHeight = 50; } // act gravitate(False); // zeros are iffy, should be calling some Manager method int dw = DisplayWidth(display(), 0), dh = DisplayHeight(display(), 0); if (m_w < m_minWidth) { m_w = m_minWidth; m_fixedSize = False; reshape = True; } if (m_h < m_minHeight) { m_h = m_minHeight; m_fixedSize = False; reshape = True; } if (m_w > dw - 8) m_w = dw - 8; if (m_h > dh - 8) m_h = dh - 8; if (m_x > dw - m_border->xIndent()) { m_x = dw - m_border->xIndent(); } if (m_y > dh - m_border->yIndent()) { m_y = dh - m_border->yIndent(); } if (m_x < m_border->xIndent()) m_x = m_border->xIndent(); if (m_y < m_border->yIndent()) m_y = m_border->yIndent(); m_border->configure(m_x, m_y, m_w, m_h, 0L, Above); if (mapped) m_reparenting = True; if (reshape && !m_fixedSize) XResizeWindow(d, m_window, m_w, m_h); XSetWindowBorderWidth(d, m_window, 0); m_border->reparent(); // (support for shaped windows absent) XAddToSaveSet(d, m_window); m_managed = True; if (shouldHide) hide(); else { XMapWindow(d, m_window); m_border->map(); setState(NormalState); if (CONFIG_CLICK_TO_FOCUS || (m_transient != None && activeClient() && activeClient()->m_window == m_transient)) { activate(); mapRaised(); } else { deactivate(); } } if (activeClient() && !isActive()) { activeClient()->installColormap(); } if (CONFIG_AUTO_RAISE) { m_windowManager->stopConsideringFocus(); focusIfAppropriate(False); } }
void Client::init() { XGrabServer(display()); // reparent client with parent (qt) XSetWindowBorderWidth(display(), clientId, 0); //client XSetWindowBorderWidth(display(), winId(), 0); //parent XReparentWindow(display(), clientId, winId(), BORDER_WIDTH, Titlebar::getPreferedHeight(0)); qDebug() << "CLIENT INIT - Reparent window:" << clientId << "with Qt parent:" << winId(); XSetWindowAttributes at; at.event_mask = DECOR_EVENT_MASK; XChangeWindowAttributes(display(), winId(), CWEventMask, &at); at.event_mask = CLIENT_EVENT_MASK; XChangeWindowAttributes(display(), clientId, CWEventMask, &at); XAddToSaveSet(display(), clientId); XGrabButton(display(), Button1, AnyModifier, clientId, FALSE, ButtonPressMask|ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None); // get initial client geometry XWindowAttributes attr; XGetWindowAttributes(display(), clientId, &attr); n_px = attr.x; n_py = attr.y; base_w = attr.width; base_h = attr.height; fixSizes(); n_pw = base_w;// + DBL_BORDER_WIDTH; n_ph = base_h + TITLEBAR_HEIGHT + 8; getWMHints(); getAppName(); getWMName(); getWMProtocols(); windowRole = Atoms::windowType(clientId); int bx, by; if (windowRole == Atoms::Splash) { bx = by = 0; n_ph = n_ph - TITLEBAR_HEIGHT - 8; } else { bx = BORDER_WIDTH; by = TITLEBAR_HEIGHT; } XMoveResizeWindow(display(), clientId, bx, by, base_w, base_h); // move (in desktop center) and resize parent (qt) n_px = (desktop->width()-base_w)/2; n_py = ((desktop->height()-dock->height() - n_ph)*2)/3 + tbHeight; qDebug() << "desktop h = " << desktop->height() << "dock h = " << dock->height(); qDebug() << "n_px = " << n_px << " n_py = " << n_py << " base_w = " << base_w << " base_h = " << base_h; move(n_px, n_py); resize(n_pw, n_ph); createDecor(); // map client show(); XMapWindow(display(), clientId); XSync(display(), false); XUngrabServer(display()); maximized = false; // TODO: get and restore initial client state clientState = NormalState; }
void Frame::init() { maximized = false; set_state(1); state = "WithdrawnState"; shaped = false; XSelectInput(QX11Info::display(), winId(), KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | KeymapStateMask | ButtonMotionMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask | FocusChangeMask | VisibilityChangeMask | ExposureMask | StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask); XSetWindowAttributes at; at.event_mask = ColormapChangeMask|PropertyChangeMask; XChangeWindowAttributes(QX11Info::display(), c_win, CWEventMask, &at); XGrabServer(QX11Info::display()); // get the client geometry get_client_geometry(); // get the client hints get_wm_hints(); // get the client normal hints get_wm_normal_hints(); // get the client prot get_wm_protocols(); // get the client icon to show on header get_icon(); // get the client name get_wm_name(); // set the frame geometry set_frame_geometry(); // set the window modality set_window_modality(); shaped = query_shape(); if (shaped) reshape(); XSetWindowBorderWidth(QX11Info::display(), c_win, 0); //client XSetWindowBorderWidth(QX11Info::display(), winId(), 0); //frame // *** THE MOST IMPORTANT FUNCTION *** // reparent client with frame XReparentWindow(QX11Info::display(), c_win, winId(), lateral_bdr_width, top_bdr_height); qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; qDebug() << "Reparent Client:" << c_win << "with Frame:" << winId() << "- Name:" << cl_name(); qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; XAddToSaveSet(QX11Info::display(), c_win); // move and resize client XMoveResizeWindow(QX11Info::display(), c_win, lateral_bdr_width, top_bdr_height+3, client_w, client_h); //if the frame is too large, maximize it if (frame_w >= QApplication::desktop()->width()-20 || frame_h >= QApplication::desktop()->height()-40) { maximize_it(); } else // normal size { // move the frame in desktop center and resize move((QApplication::desktop()->width()/2)-(frame_w/2), (QApplication::desktop()->height()/2)-(frame_h/2)); resize(frame_w, frame_h); } qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; qDebug() << "Frame_x:" << frame_x << "Frame_y:" << frame_y << "Frame_w:" << frame_w << "Frame_h:" << frame_h; qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << "\n"; if (frame_type != "Splash") // Splash frame have no header and no border { // create frame borders/header create_borders(); // set the header pixmap set_inactive(); splash = false; } else { qDebug() << "Frame:" << winId() << "Name:" << wm_name << "is Splash type"; splash = true; } // send _NET_ACTIVE_WINDOW property Atom _net_active_window = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", False); XClientMessageEvent xev; xev.type = ClientMessage; xev.window = c_win; xev.message_type = _net_active_window; xev.format = 32; xev.data.l[0] = 1; // from application xev.data.l[1] = CurrentTime; xev.data.l[2] = 0; XSendEvent(QX11Info::display(), QApplication::desktop()->winId(), False, StructureNotifyMask, (XEvent *)&xev); // map client XMapWindow(QX11Info::display(), c_win); XSync(QX11Info::display(), false); XUngrabServer(QX11Info::display()); // show frame show(); }
/** @brief Reparents the specified framed_window to a newly created frame. @return returns 1 if successful or 0 if no window was created. @todo A the moment each pointer is totally valid, in the future it will merely be an alias from another datastructure. **/ int create_frame(Display *display, struct Frame* frame , Window framed_window, struct Popup_menu *window_menu, struct Separators *seps, const struct Workarea *workarea, struct Themes *themes , struct Cursors *cursors, struct Atoms *atoms) { XWindowAttributes get_attributes; //printf("Creating frames->list[%d] with window %lu, connection %lu\n" //, frames->used, (unsigned long)framed_window, (unsigned long)display); //add this window to the save set as soon as possible so that if an error occurs it is still available XAddToSaveSet(display, framed_window); XSync(display, False); XGetWindowAttributes(display, framed_window, &get_attributes); /*** Set up defaults ***/ frame->focussed = False; frame->sticky = False; frame->window_name = NULL; frame->framed_window = framed_window; frame->type = unknown; frame->theme_type = unknown; frame->mode = unset; frame->state = none; frame->wants_attention = False; frame->transient = 0; frame->width_inc = 1; frame->height_inc = 1; frame->menu.item = 0; frame->w_inc_offset = 0; frame->h_inc_offset = 0; frame->w = get_attributes.width; frame->h = get_attributes.height; get_frame_type_and_mode (display, frame, atoms, themes); frame->x = get_attributes.x - themes->window_type[frame->theme_type][window].x; frame->y = get_attributes.y - themes->window_type[frame->theme_type][window].y; frame->hspace = 0 - themes->window_type[frame->theme_type][window].w; frame->vspace = 0 - themes->window_type[frame->theme_type][window].h; // This is not set to the something sensive, like the size of the workarea // as it may change and we can't tell if it's a default value or a real // one set by the client. // Instead, always use the MIN of the workarea dimension and these values frame->max_width = INT_MAX; frame->max_height = INT_MAX; //prevent overly small windows with these sensible defaults frame->min_width = MINWIDTH + frame->hspace; frame->min_height = MINHEIGHT + frame->vspace; #ifdef ALLOW_OVERSIZE_WINDOWS_WITHOUT_MINIMUM_HINTS Screen* screen = DefaultScreenOfDisplay(display); /* Ugh Horrible. */ /* Many apps that are resizeable ask to be the size of the screen and since windows often don't specifiy their minimum size, we have no other way of knowing if they really need to be that size or not. In case they do, this specifies that their current width is their minimum size, in the hope that it is overridden by the size hints. This kind of behaviour causes problems on small screens like the eee pc. */ if(frame->w > XWidthOfScreen(screen)) frame->min_width = frame->w; if(frame->h > XHeightOfScreen(screen)) frame->min_height = frame->h; #endif /* This requires hspace and vspace to be set as well as the incremental hints */ get_frame_hints(display, frame); frame_type_settings(display, frame, workarea); //Don't manage splash screens, they just cause the workspace to be created and instantly destroyed if(frame->type == splash) { XMapWindow(display, framed_window); XFlush(display); return 0; } get_frame_state(display, frame, atoms); create_frame_subwindows(display, frame, themes, cursors); create_frame_name(display, window_menu, frame, themes, atoms); get_frame_wm_hints(display, frame); //this might need to change the focus, it's mode (to hidden) and so on get_frame_strut_hints_as_normal_hints(display, frame, atoms); //_NET_FRAME_EXTENTS, left, right, top, bottom, CARDINAL[4]/32 int32_t ewmh_frame_extents[4] = { themes->window_type[frame->theme_type][window].x , themes->window_type[frame->theme_type][window].y , - themes->window_type[frame->theme_type][window].x - themes->window_type[frame->theme_type][window].w , - themes->window_type[frame->theme_type][window].y - themes->window_type[frame->theme_type][window].h }; XChangeProperty(display, framed_window, atoms->frame_extents, XA_CARDINAL , 32, PropModeReplace, (unsigned char *)ewmh_frame_extents, 4); XSetWindowBorderWidth(display, framed_window, 0); change_frame_mode(display, frame, unset, workarea, themes); #ifdef CRASH_ON_BUG XGrabServer(display); XSetErrorHandler(supress_xerror); #endif XSelectInput(display, framed_window, 0); //reparent the framed_window to frame->widgets[window].widget XReparentWindow(display, framed_window, frame->widgets[window].widget, 0, 0); //for some odd reason the reparent only reports an extra unmap event if the window was already unmapped XRaiseWindow(display, framed_window); XMapWindow(display, frame->widgets[window].widget); #ifdef CRASH_ON_BUG XSetErrorHandler(NULL); XUngrabServer(display); #endif XSelectInput(display, framed_window, PropertyChangeMask); //Property notify is used to update titles XSelectInput(display, frame->widgets[window].widget , SubstructureRedirectMask | SubstructureNotifyMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask); //Some windows only send the destroy event (e.g., gimp splash screen) XSync(display, False); //Intercept clicks so we can set the focus and possibly raise floating windows XGrabButton(display, Button1, 0, frame->widgets[window].widget , False, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None); //do it for numlock as well XGrabButton(display, Button1, Mod2Mask, frame->widgets[window].widget , False, ButtonPressMask, GrabModeSync, GrabModeAsync, None, None); frame->w += frame->hspace; frame->h += frame->vspace; check_frame_limits(display, frame, workarea, themes); resize_frame(display, frame, themes); stack_frame(display, frame, seps); change_frame_state(display, frame, frame->state, seps, workarea, themes, atoms); XMoveResizeWindow(display, framed_window, 0, 0, frame->w - frame->hspace, frame->h - frame->vspace); XMoveWindow(display, framed_window, 0, 0); XMapWindow(display, framed_window); XFlush(display); save_frame_initial_state(frame); return 1; }