/** * Handles the release of a mouse button. This event is only expected when * a placeholder is going to be released, so the only possible action is to * stop moving/resizing. */ void XEvents::handle_buttonrelease() { Window expected_placeholder = m_xmodel.get_move_resize_placeholder(); // If this is *not* the current placeholder, then bail if (expected_placeholder != m_event.xbutton.window) return; MoveResizeState state = m_xmodel.get_move_resize_state(); Window client = m_xmodel.get_move_resize_client(); // Figure out the attributes of the placeholder, so that way we can do // the movements/resizes XWindowAttributes attrs; m_xdata.get_attributes(expected_placeholder, attrs); switch (state) { case MR_MOVE: m_clients.stop_moving(client, Dimension2D(attrs.x, attrs.y)); break; case MR_RESIZE: m_clients.stop_resizing(client, Dimension2D(attrs.width, attrs.height)); break; } }
Image::Image(size_t width, size_t height, SamplingDefinition scheme) : imageSize(width, height), simulatedSize( width + (width % scheme.stepSize.width == 0 ? 0 : scheme.stepSize.width - width % scheme.stepSize.width), height + (height % scheme.stepSize.height == 0 ? 0 : scheme.stepSize.height - height % scheme.stepSize.height)), channelSizes { Dimension2D(simulatedSize) , Dimension2D(simulatedSize) , Dimension2D(simulatedSize) }, samplingScheme(scheme) { channels = std::make_unique<ImageData>(simulatedSize); blocksPerChannel[0] = blocksPerChannel[1] = blocksPerChannel[2] = simulatedSize.width * simulatedSize.height / 8; }
/** * Changes the location of a client. */ void ClientModel::change_location(Window client, Dimension x, Dimension y) { // See whether the client should end up on a new desktop with its new // location const Box &old_desktop = m_screen[client]; Crt *new_screen = m_crt_manager.screen_of_coord(x, y); const Box &new_desktop = m_crt_manager.box_of_screen(new_screen); m_location[client] = Dimension2D(x, y); m_changes.push(new ChangeLocation(client, x, y)); if (old_desktop != new_desktop) to_screen_box(client, new_desktop); }
/** * Adds a window - this is exposed specifically so that smallwm.cpp can * access this method when it imports existing windows. * * @param window The window to add. */ void XEvents::add_window(Window window) { // First, test if this client is already known to us - if it is, then // move it onto the current desktop if (m_clients.is_client(window)) { Desktop const *mapped_desktop = m_clients.find_desktop(window); // Icons must be uniconified if (mapped_desktop->is_icon_desktop()) m_clients.deiconify(window); // Moving/resizing clients must stop being moved/resized if (mapped_desktop->is_moving_desktop() || mapped_desktop->is_resizing_desktop()) { Window placeholder = m_xmodel.get_move_resize_placeholder(); m_xmodel.exit_move_resize(); XWindowAttributes placeholder_attr; m_xdata.get_attributes(placeholder, placeholder_attr); if (mapped_desktop->is_moving_desktop()) m_clients.stop_moving(window, Dimension2D(placeholder_attr.x, placeholder_attr.y)); else if (mapped_desktop->is_resizing_desktop()) m_clients.stop_resizing(window, Dimension2D(placeholder_attr.width, placeholder_attr.height)); } // Clients which are currently stuck on all desktops don't need to have // anything done to them. Everybody else has to be moved onto the // current desktop. if (!mapped_desktop->is_all_desktop()) m_clients.client_reset_desktop(window); return; } // So, this isn't an existing client. We have to figure out now if this is // even a client *at all* - override_redirect indicates if this client does // (false) or does not (true) want to be managed XWindowAttributes win_attr; m_xdata.get_attributes(window, win_attr); if (win_attr.override_redirect) return; // This is a new, manageable client - register it with the client database. // This requires we know 3 things: // - What the client wants, with regards to its initial state - either // visible or iconified // - The client's position (we know this one) // - The client's size (we know this one too) // // The information about the initial state is given by XWMHints XWMHints hints; bool has_hints = m_xdata.get_wm_hints(window, hints); InitialState init_state = IS_VISIBLE; if (has_hints && hints.flags & StateHint && hints.initial_state == IconicState) init_state = IS_HIDDEN; m_clients.add_client(window, init_state, Dimension2D(win_attr.x, win_attr.y), Dimension2D(win_attr.width, win_attr.height)); // If the client is a dialog, this will be represented in the transient // hint (which is None if the client is not a dialog, or not-None if it is) if (m_xdata.get_transient_hint(window) != None) m_clients.set_layer(window, DIALOG_LAYER); // Finally, execute the actions tied to the window's class std::string win_class; m_xdata.get_class(window, win_class); if (m_config.classactions.count(win_class) > 0 && init_state != IS_HIDDEN) { ClassActions &action = m_config.classactions[win_class]; if (action.actions & ACT_STICK) m_clients.toggle_stick(window); if (action.actions & ACT_MAXIMIZE) maximize_client(window); if (action.actions & ACT_SETLAYER) m_clients.set_layer(window, action.layer); if (action.actions & ACT_SNAP) snap_client(window, action.snap); if (action.actions & ACT_MOVE_X || action.actions & ACT_MOVE_Y) { Dimension scr_width, scr_height; m_xdata.get_screen_size(scr_width, scr_height); Dimension win_x_pos = win_attr.x; Dimension win_y_pos = win_attr.y; if (action.actions & ACT_MOVE_X) win_x_pos = scr_width * action.relative_x; if (action.actions & ACT_MOVE_Y) win_y_pos = scr_height * action.relative_y; if (win_attr.x != win_x_pos || win_attr.x != win_y_pos) m_clients.change_location(window, win_x_pos, win_y_pos); } } }
/** * Updates the size of a client without causing a change. * * This is meant to inform the model of changes that happened because of the * client doing things on its own, and not because of us. */ void ClientModel::update_size(Window client, Dimension width, Dimension height) { if (width > 0 && height > 0) m_size[client] = Dimension2D(width, height); }