diff options
author | Mavridis Philippe <mavridisf@gmail.com> | 2024-11-13 17:48:10 +0200 |
---|---|---|
committer | Mavridis Philippe <mavridisf@gmail.com> | 2024-11-19 19:10:45 +0200 |
commit | c913d416f7102f9d091c39dfd32db9b802f32983 (patch) | |
tree | 8b5482a0f089a87d37fa204e724d2c78857b08f4 | |
parent | 1afb78e598cc0d8c320e98c963cb98ab7935435f (diff) | |
download | tdebase-c913d416f7102f9d091c39dfd32db9b802f32983.tar.gz tdebase-c913d416f7102f9d091c39dfd32db9b802f32983.zip |
TWin: add "Grid tiling" featurefeat/grid-tiling
Signed-off-by: Mavridis Philippe <mavridisf@gmail.com>
-rw-r--r-- | twin/client.cpp | 5 | ||||
-rw-r--r-- | twin/client.h | 9 | ||||
-rw-r--r-- | twin/events.cpp | 75 | ||||
-rw-r--r-- | twin/geometry.cpp | 48 | ||||
-rw-r--r-- | twin/kcmtwin/twinoptions/windows.cpp | 30 | ||||
-rw-r--r-- | twin/kcmtwin/twinoptions/windows.h | 3 | ||||
-rw-r--r-- | twin/options.cpp | 1 | ||||
-rw-r--r-- | twin/options.h | 2 | ||||
-rw-r--r-- | twin/workspace.cpp | 13 | ||||
-rw-r--r-- | twin/workspace.h | 2 |
10 files changed, 174 insertions, 14 deletions
diff --git a/twin/client.cpp b/twin/client.cpp index b8f00746e..5d831acec 100644 --- a/twin/client.cpp +++ b/twin/client.cpp @@ -123,7 +123,10 @@ Client::Client( Workspace *ws ) opacity_( 0 ), demandAttentionKNotifyTimer( NULL ), activeMaximizing(false), - activeTiled(false) + activeTiled(false), + gridTilingMode(false), + hGridTiles(1), + vGridTiles(1) // SELI do all as initialization { autoRaiseTimer = 0; diff --git a/twin/client.h b/twin/client.h index a59b20acd..c05e8f116 100644 --- a/twin/client.h +++ b/twin/client.h @@ -242,6 +242,11 @@ class Client : public TQObject, public KDecorationDefines TQRect activeBorderMaximizeGeometry(); void tileToBorder(ActiveBorder border); + TQSize gridTileSize(); + void handleGridTiling(TQRect geom); + void handleGridTilesChange(TQt::Orientation o, int delta); + bool isGridTiling() { return gridTilingMode; } + void growHorizontal(); void shrinkHorizontal(); void growVertical(); @@ -618,6 +623,10 @@ class Client : public TQObject, public KDecorationDefines ActiveMaximizingMode activeMode; ActiveBorder currentActiveBorder; + bool gridTilingMode; + int vGridTiles, hGridTiles; + TQRect gridTileGeom; + friend bool performTransiencyCheck(); bool minimized_before_suspend; }; diff --git a/twin/events.cpp b/twin/events.cpp index 3d3ba999c..11d621487 100644 --- a/twin/events.cpp +++ b/twin/events.cpp @@ -228,13 +228,30 @@ bool Workspace::workspaceEvent( XEvent * e ) { was_user_interaction = true; KKeyNative keyX( (XEvent*)e ); - uint keyQt = keyX.keyCodeQt(); + kdDebug(125) << "Workspace::keyPress( " << keyX.key().toString() << " )" << endl; if (movingClient) + { + uint keyQt = keyX.keyCodeQt(); + keyQt = keyQt & TQt::SHIFT ? keyQt ^ TQt::SHIFT : keyQt; + + // Check for grid tiling + if (options->gridTiling) { - movingClient->keyPressEvent(keyQt); - return true; + if (keyQt == TQt::Key_BracketLeft || keyQt == TQt::Key_BracketRight) + { + movingClient->handleGridTilesChange(TQt::Horizontal, keyQt == Key_BracketRight ? 1 : -1); + return true; + } + else if (keyQt == TQt::Key_BraceLeft || keyQt == TQt::Key_BraceRight) + { + movingClient->handleGridTilesChange(TQt::Vertical, keyQt == Key_BraceRight ? 1 : -1); + return true; + } } + movingClient->keyPressEvent(keyX.keyCodeQt()); + return true; + } if( tab_grab || control_grab ) { tabBoxKeyPress( keyX ); @@ -1338,9 +1355,51 @@ bool Client::eventFilter( TQObject* o, TQEvent* e ) return false; } +void Client::handleGridTilesChange(TQt::Orientation o, int delta) +{ + if (!isMove() || !isResizable()) return; + + int *gridTiles = (o == TQt::Horizontal ? &hGridTiles : &vGridTiles); + if (delta > 0) + { + if (!gridTilingMode) + { + gridTilingMode = true; + hGridTiles = 1; + vGridTiles = 1; + } + } + + if ((*gridTiles) + delta > 0) (*gridTiles) += delta; + + // Single big tile == cancel grid tiling + if (hGridTiles == 1 && vGridTiles == 1) + { + gridTilingMode = false; + } + + // If the resulting tile is too small to accomodate the window, + // then undo the tile count change + TQSize tileSize = gridTileSize(); + TQSize minWSize = minSize(); + if (tileSize.width() < minWSize.width() || + tileSize.height() < minWSize.height()) + { + (*gridTiles) -= delta; + } + + clearbound(); +} + // return value matters only when filtering events before decoration gets them bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ) { + if (options->gridTiling && button > 7 && button < 10) + { + handleGridTilesChange(state & ShiftMask ? TQt::Vertical : TQt::Horizontal, + button == 9 ? 1 : -1); + } + if (buttonDown) { if( w == wrapperId()) @@ -1353,6 +1412,7 @@ bool Client::buttonPressEvent( Window w, int button, int state, int x, int y, in // FRAME something out of this would be processed before it gets decorations updateUserTime(); workspace()->setWasUserInteraction(); + uint keyModX = (options->keyCmdAllModKey() == TQt::Key_Meta) ? KKeyNative::modX(KKey::WIN) : KKeyNative::modX(KKey::ALT); @@ -1502,7 +1562,7 @@ void Client::processMousePressEvent( TQMouseEvent* e ) } // return value matters only when filtering events before decoration gets them -bool Client::buttonReleaseEvent( Window w, int /*button*/, int state, int x, int y, int x_root, int y_root ) +bool Client::buttonReleaseEvent( Window w, int button, int state, int x, int y, int x_root, int y_root ) { if( w == decorationId() && !buttonDown) return false; @@ -1511,6 +1571,13 @@ bool Client::buttonReleaseEvent( Window w, int /*button*/, int state, int x, int XAllowEvents(tqt_xdisplay(), SyncPointer, CurrentTime ); //tqt_x_time); return true; } + + // Grid tiling + if (isMove() && button > 7 && button < 10) + { + return true; + } + if( w != frameId() && w != decorationId() && w != moveResizeGrabWindow()) return true; x = this->x(); // translate from grab window to local coords diff --git a/twin/geometry.cpp b/twin/geometry.cpp index 581c07ac1..e28a81f85 100644 --- a/twin/geometry.cpp +++ b/twin/geometry.cpp @@ -1360,6 +1360,20 @@ TQSize Client::maxSize() const return rules()->checkMaxSize( TQSize( xSizeHint.max_width, xSizeHint.max_height )); } +TQSize Client::gridTileSize() +{ + TQRect max = workspace()->clientArea(MaximizeArea, TQCursor::pos(), workspace()->currentDesktop()); + return TQSize(max.width() / hGridTiles, max.height() / vGridTiles); +} + +void Client::handleGridTiling(TQRect geom) +{ + gridTileGeom = geom; + clearbound(); + positionGeometryTip(); + drawbound(geom); +} + /*! Auxiliary function to inform the client about the current window configuration. @@ -2273,7 +2287,7 @@ void Client::positionGeometryTip() { } // position of the frame, size of the window itself - TQRect wgeom(isActiveBorderMaximizing() ? activeBorderMaximizeGeometry() : moveResizeGeom); + TQRect wgeom(gridTilingMode ? gridTileGeom : (isActiveBorderMaximizing() ? activeBorderMaximizeGeometry() : moveResizeGeom)); wgeom.setWidth(wgeom.width() - (width() - clientSize().width())); wgeom.setHeight(isShade() ? 0 : wgeom.height() - (height() - clientSize().height())); @@ -2402,11 +2416,15 @@ void Client::finishMoveResize( bool cancel ) { leaveMoveResize(); - if (!isActiveBorderMaximizing()) { - setGeometry(cancel ? initialMoveResizeGeom : moveResizeGeom); + if (gridTilingMode) + { + setGeometry(gridTileGeom); + gridTilingMode = false; + hGridTiles = 1; + vGridTiles = 1; } - else + else if (isActiveBorderMaximizing()) { kdDebug() <<"finishing moveresize in active mode, cancel is " << cancel << endl; activeMaximizing = false; @@ -2428,6 +2446,10 @@ void Client::finishMoveResize( bool cancel ) activeTiledOrigGeom.moveTopLeft(rect().topLeft()); } + else { + setGeometry(cancel ? initialMoveResizeGeom : moveResizeGeom); + } + checkMaximizeGeometry(); // FRAME update(); Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd ); @@ -2690,13 +2712,21 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root) { if (update) { + if (gridTilingMode) + { + TQSize gridSize(hGridTiles, vGridTiles); + workspace()->checkGridTiling(globalPos, gridSize); + } + bool active = isActiveBorderMaximizing(); - auto mode = active ? options->tilingMode - : isResize() ? options->resizeMode : options->moveMode; + auto mode = (gridTilingMode || active) ? options->tilingMode : + (isResize() ? options->resizeMode : options->moveMode); + + TQRect geom = gridTilingMode ? gridTileGeom : (active ? activeBorderMaximizeGeometry() : moveResizeGeom); if (rules()->checkMoveResizeMode(mode) == Options::Opaque) { - setGeometry(active ? activeBorderMaximizeGeometry() : moveResizeGeom); + setGeometry(geom); positionGeometryTip(); } else if (rules()->checkMoveResizeMode(mode) == Options::Transparent) @@ -2708,10 +2738,10 @@ void Client::handleMoveResize(int x, int y, int x_root, int y_root) { */ clearbound(); positionGeometryTip(); - drawbound(active ? activeBorderMaximizeGeometry() : moveResizeGeom); + drawbound(geom); } } - if (isMove()) { + if (isMove() && !gridTilingMode) { workspace()->checkActiveBorder(globalPos, get_tqt_x_time()); } } diff --git a/twin/kcmtwin/twinoptions/windows.cpp b/twin/kcmtwin/twinoptions/windows.cpp index 9d8e8d617..affc09532 100644 --- a/twin/kcmtwin/twinoptions/windows.cpp +++ b/twin/kcmtwin/twinoptions/windows.cpp @@ -85,6 +85,7 @@ #define KWIN_ACTIVE_BORDERS "ActiveBorders" #define KWIN_ACTIVE_BORDER_DELAY "ActiveBorderDelay" #define KWIN_ACTIVE_BORDER_DISTANCE "ActiveBorderDistance" +#define KWIN_GRID_TILING "GridTiling" // legacy options #define KWIN_OLD_ACTIVE_BORDERS "ElectricBorders" @@ -673,6 +674,18 @@ KActiveBorderConfig::KActiveBorderConfig(bool _standAlone, TDEConfig *_config, T " mouse is close enough, making them easier to activate but also more prone" " to false activations.")); + gridTiling = new TQCheckBox(i18n("Enable grid tiling"), active_box); + TQWhatsThis::add(gridTiling, i18n("This feature allows you to easily place your windows " + "in a grid by using the bracket keys or the history " + "navigation buttons on your mouse to manipulate the " + "count of grid tiles (the Shift key, while pressed, " + "modifies the edited orientation). " + "Unlike traditional active borders tiling, to preview " + "window placement you only need to press a mouse button " + "while dragging the window and the decision is finalized " + "once you stop dragging the window. Reducing the grid " + "size to 1x1 cancels grid tiling.")); + active_vbox->addSpacing(10); active_vbox->addWidget(active_func_label); active_vbox->addWidget(active_disable); @@ -685,6 +698,8 @@ KActiveBorderConfig::KActiveBorderConfig(bool _standAlone, TDEConfig *_config, T active_vbox->addWidget(distance); active_vbox->addSpacing(15); active_vbox->addWidget(tilingOpaque); + active_vbox->addSpacing(15); + active_vbox->addWidget(gridTiling); connect(active_box, TQ_SIGNAL(clicked(int)), this, TQ_SLOT(updateActiveBorders())); @@ -725,6 +740,8 @@ void KActiveBorderConfig::load() { else if (tilingMode == "Transparent") setTilingMode(TRANSPARENT); + setGridTiling(config->readBoolEntry(KWIN_GRID_TILING, false)); + emit TDECModule::changed(false); } @@ -735,6 +752,8 @@ void KActiveBorderConfig::save() { config->writeEntry(KWIN_ACTIVE_BORDER_DELAY, getActiveBorderDelay()); config->writeEntry(KWIN_ACTIVE_BORDER_DISTANCE, getActiveBorderDistance()); + config->writeEntry(KWIN_GRID_TILING, getGridTiling()); + // remove replaced legacy entries config->deleteEntry(KWIN_OLD_ACTIVE_BORDERS); config->deleteEntry(KWIN_OLD_ACTIVE_BORDER_DELAY); @@ -760,6 +779,7 @@ void KActiveBorderConfig::defaults() { setActiveBorderDelay(150); setActiveBorderDistance(10); setTilingMode(TRANSPARENT); + setGridTiling(false); emit TDECModule::changed(true); } @@ -798,6 +818,11 @@ int KActiveBorderConfig::getActiveBorderDistance() { return distance->value(); } +bool KActiveBorderConfig::getGridTiling() +{ + return gridTiling->isChecked(); +} + void KActiveBorderConfig::setActiveBorders(int i) { switch(i) { @@ -827,6 +852,11 @@ void KActiveBorderConfig::setActiveBorderDistance(int d) { distance->setValue(d); } +void KActiveBorderConfig::setGridTiling(bool on) +{ + gridTiling->setChecked(on); +} + KAdvancedConfig::~KAdvancedConfig () { if (standAlone) diff --git a/twin/kcmtwin/twinoptions/windows.h b/twin/kcmtwin/twinoptions/windows.h index 80c9e76d7..90178e822 100644 --- a/twin/kcmtwin/twinoptions/windows.h +++ b/twin/kcmtwin/twinoptions/windows.h @@ -212,11 +212,13 @@ class KActiveBorderConfig : public TDECModule int getActiveBorderDelay(); int getActiveBorderDistance(); int getTilingMode(); + bool getGridTiling(); void setActiveBorders(int); void setActiveBorderDelay(int); void setActiveBorderDistance(int); void setTilingMode(int); + void setGridTiling(bool); TQButtonGroup *active_box; TQRadioButton *active_disable; @@ -229,6 +231,7 @@ class KActiveBorderConfig : public TDECModule TQWidget *active_desktop_conf; TQWidget *active_tile_conf; TQCheckBox *tilingOpaque; + TQCheckBox *gridTiling; TDEConfig *config; bool standAlone; diff --git a/twin/options.cpp b/twin/options.cpp index 46c557b4a..1574cfa36 100644 --- a/twin/options.cpp +++ b/twin/options.cpp @@ -54,6 +54,7 @@ unsigned long Options::updateSettings() moveMode = stringToMoveResizeMode(config->readEntry("MoveMode", "Opaque")); resizeMode = stringToMoveResizeMode(config->readEntry("ResizeMode", "Opaque")); tilingMode = stringToMoveResizeMode(config->readEntry("TilingMode", "Opaque")); + gridTiling = config->readBoolEntry("GridTiling", false); show_geometry_tip = config->readBoolEntry("GeometryTip", false); reset_maximized_window_geometry = config->readBoolEntry("ResetMaximizedWindowGeometry", false); tabboxOutline = config->readBoolEntry("TabboxOutline", true); diff --git a/twin/options.h b/twin/options.h index 41d1340a7..67166f605 100644 --- a/twin/options.h +++ b/twin/options.h @@ -154,6 +154,8 @@ class Options : public KDecorationOptions static MoveResizeMode stringToMoveResizeMode( const TQString& s ); static const char* moveResizeModeToString( MoveResizeMode mode ); + bool gridTiling; + Placement::Policy placement; bool focusPolicyIsReasonable() diff --git a/twin/workspace.cpp b/twin/workspace.cpp index 23661e6a0..26ff7c2b6 100644 --- a/twin/workspace.cpp +++ b/twin/workspace.cpp @@ -2519,6 +2519,19 @@ void Workspace::unreserveActiveBorder( ActiveBorder border ) TQTimer::singleShot(0, this, TQ_SLOT(updateActiveBorders())); } +void Workspace::checkGridTiling(const TQPoint &pos, TQSize &gridSize) +{ + TQSize tileSize = movingClient->gridTileSize(); + TQRect area = clientArea(MaximizeArea, pos, currentDesktop()); + + // Compute target geometry based on current pos + int x = 0, y = 0; + while (x + tileSize.width() < pos.x() && x < area.width()) x += tileSize.width(); + while (y + tileSize.height() < pos.y() && y < area.height()) y += tileSize.height(); + + movingClient->handleGridTiling(TQRect(x, y, tileSize.width(), tileSize.height())); +} + void Workspace::checkActiveBorder(const TQPoint &pos, Time now) { Time treshold_set = options->activeBorderDelay(); // set timeout diff --git a/twin/workspace.h b/twin/workspace.h index 28da82ff0..44b03f677 100644 --- a/twin/workspace.h +++ b/twin/workspace.h @@ -161,6 +161,8 @@ class Workspace : public TQObject, public KWinInterface, public KDecorationDefin void unreserveActiveBorder(ActiveBorder border); void reserveActiveBorderSwitching(bool reserve); + void checkGridTiling(const TQPoint &pos, TQSize &gridSize); + /** * Returns the current virtual desktop of this workspace */ |