aboutsummaryrefslogtreecommitdiff
path: root/libLumina
diff options
context:
space:
mode:
authorKen Moore <ken@pcbsd.org>2015-01-01 10:18:35 -0500
committerKen Moore <ken@pcbsd.org>2015-01-01 10:18:35 -0500
commit64c9ecca216ce03287908c510a7af3adff112832 (patch)
treeebfdb821a450121a8ebd9352b2c57ce0cdd3d0ef /libLumina
parentMake sure that any argv[] -> QString translations from CLI input are run thro... (diff)
downloadlumina-64c9ecca216ce03287908c510a7af3adff112832.tar.gz
lumina-64c9ecca216ce03287908c510a7af3adff112832.tar.bz2
lumina-64c9ecca216ce03287908c510a7af3adff112832.zip
Large update of XLib -> XCB usage
1) Add ability for task manager to minimize/maximize window from details menu 2) Add quick check/movement of new windows to make sure they are not underneath any panels
Diffstat (limited to 'libLumina')
-rw-r--r--libLumina/LuminaX11.cpp153
-rw-r--r--libLumina/LuminaX11.h9
2 files changed, 147 insertions, 15 deletions
diff --git a/libLumina/LuminaX11.cpp b/libLumina/LuminaX11.cpp
index 03a33dd0..2230c1ff 100644
--- a/libLumina/LuminaX11.cpp
+++ b/libLumina/LuminaX11.cpp
@@ -26,19 +26,6 @@
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>
-//xcb_ewmh_connection_t ewmh_handle;
-
-//===== Get EWMH connection handle =====
-/*xcb_ewmh_connection_t* LX11::EWMH_C(){
- static bool firstrun = true;
- if(firstrun){
- qDebug() << "Init EWMH structure";
- xcb_ewmh_init_atoms(QX11Info::connection(), &ewmh_handle);
- firstrun = false;
- }
- qDebug() << "Return EWMH structure pointer:" << &ewmh_handle;
- return &ewmh_handle;
-}*/
//===== WindowList() ========
QList<WId> LX11::WindowList(){
@@ -888,6 +875,19 @@ unsigned int LXCB::CurrentWorkspace(){
return wkspace;
}
+// === RegisterVirtualRoots() ===
+void LXCB::RegisterVirtualRoots(QList<WId> roots){
+ //First convert the QList into the proper format
+ xcb_window_t *list = new xcb_window_t[ roots.length() ];
+ for(int i=0; i<roots.length(); i++){
+ list[i] = roots[i]; //move from the QList to the array
+ }
+ //Now set the property
+ xcb_ewmh_set_virtual_roots(&EWMH, 0, roots.length(), list);
+ //Now delete the temporary array from memory
+ delete list;
+}
+
// === WindowClass() ===
QString LXCB::WindowClass(WId win){
QString out;
@@ -912,6 +912,49 @@ unsigned int LXCB::WindowWorkspace(WId win){
return wkspace;
}
+// === WindowGeometry() ===
+QRect LXCB::WindowGeometry(WId win, bool includeFrame){
+ QRect geom;
+ xcb_get_geometry_cookie_t cookie = xcb_get_geometry(QX11Info::connection(), win);
+ xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(QX11Info::connection(), cookie, NULL);
+ //qDebug() << "Get Window Geometry:" << reply;
+ if(reply != 0){
+ geom = QRect(0, 0, reply->width, reply->height); //make sure to use the origin point for the window
+ //qDebug() << " - "<<reply->x << reply->y << reply->width << reply->height;
+ free(reply);
+ if(includeFrame){
+ //Need to add/include the frame extents as well (assuming the frame info is available)
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_frame_extents_unchecked(&EWMH, win);
+ if(cookie.sequence != 0){
+ xcb_ewmh_get_extents_reply_t frame;
+ if(1== xcb_ewmh_get_frame_extents_reply(&EWMH, cookie, &frame, NULL) ){
+ //adjust the origin point to account for the frame
+ geom.translate(-frame.left, -frame.top); //move to the orign point for the frame
+ //adjust the size (include the frame sizes)
+ //geom.setWidth( geom.width() + frame.left + frame.right );
+ //geom.setHeight( geom.height() + frame.top + frame.bottom );
+ }
+ //qDebug() << " - Frame:" << frame.left << frame.right << frame.top << frame.bottom;
+ //qDebug() << " - Modified with Frame:" << geom.x() << geom.y() << geom.width() << geom.height();
+ }
+ }
+ //Now need to convert this to absolute coordinates (not parent-relavitve)
+ xcb_translate_coordinates_cookie_t tcookie = xcb_translate_coordinates(QX11Info::connection(), win, QX11Info::appRootWindow(), geom.x(), geom.y());
+ xcb_translate_coordinates_reply_t *trans = xcb_translate_coordinates_reply(QX11Info::connection(), tcookie, NULL);
+ if(trans!=0){
+ //qDebug() << " - Got Translation:" << trans->dst_x << trans->dst_y;
+ //Replace the origin point with the global position (sizing remains the same)
+ geom.moveLeft(trans->dst_x); //adjust X coordinate (no size change)
+ geom.moveTop(trans->dst_y); //adjust Y coordinate (no size change)
+ free(trans);
+ }
+ }else{
+ //Need to do another catch for this situation (probably not mapped yet)
+ }
+
+ return geom;
+}
+
// === WindowState() ===
LXCB::WINDOWSTATE LXCB::WindowState(WId win){
xcb_get_property_cookie_t cookie = xcb_ewmh_get_wm_state_unchecked(&EWMH, win);
@@ -1027,6 +1070,90 @@ void LXCB::SetAsSticky(WId win){
void LXCB::CloseWindow(WId win){
xcb_ewmh_request_close_window(&EWMH, 0, win, QX11Info::getTimestamp(), XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER);
}
+
+// === MinimizeWindow() ===
+void LXCB::MinimizeWindow(WId win){ //request that the window be unmapped/minimized
+ //Note: Fluxbox completely removes this window from the open list if unmapped manually
+ // xcb_unmap_window(QX11Info::connection(), win);
+ //xcb_flush(QX11Info::connection()); //make sure the command is sent out right away
+
+ //Need to send a client message event for the window so the WM picks it up
+ xcb_client_message_event_t event;
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = win;
+ event.type = EWMH._NET_WM_STATE;
+ event.data.data32[0] = 1; //set to toggle (switch back and forth)
+ event.data.data32[1] = EWMH._NET_WM_STATE_HIDDEN;
+ event.data.data32[2] = 0;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
+}
+
+// === ActivateWindow() ===
+void LXCB::ActivateWindow(WId win){ //request that the window become active
+ //First need to get the currently active window
+ xcb_get_property_cookie_t cookie = xcb_ewmh_get_active_window_unchecked(&EWMH, 0);
+ xcb_window_t actwin;
+ if(1 != xcb_ewmh_get_active_window_reply(&EWMH, cookie, &actwin, NULL) ){
+ actwin = 0;
+ }
+ if(actwin == win){ return; } //requested window is already active
+
+//Need to send a client message event for the window so the WM picks it up
+ xcb_client_message_event_t event;
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = win; //window to activate
+ event.type = EWMH._NET_ACTIVE_WINDOW;
+ event.data.data32[0] = 2; //pager/direct user interaction
+ event.data.data32[1] = QX11Info::getTimestamp(); //current timestamp
+ event.data.data32[2] = actwin; //currently active window (0 if none)
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
+
+}
+
+// === MaximizeWindow() ===
+void LXCB::MaximizeWindow(WId win){ //request that the window become maximized
+ //Need to send a client message event for the window so the WM picks it up
+ xcb_client_message_event_t event;
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.window = win;
+ event.type = EWMH._NET_WM_STATE;
+ event.data.data32[0] = 2; //set to toggle (switch back and forth)
+ event.data.data32[1] = EWMH._NET_WM_STATE_MAXIMIZED_VERT;
+ event.data.data32[2] = EWMH._NET_WM_STATE_MAXIMIZED_HORZ;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(QX11Info::connection(), 0, QX11Info::appRootWindow(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *) &event);
+
+}
+
+// === MoveResizeWindow() ===
+void LXCB::MoveResizeWindow(WId win, QRect geom){
+ //NOTE: geom needs to be in root/absolute coordinates!
+ //qDebug() << "MoveResize Window:" << geom.x() << geom.y() << geom.width() << geom.height();
+
+ //Move the window
+ /*xcb_ewmh_request_moveresize_window(&EWMH, 0, win, XCB_GRAVITY_STATIC, XCB_EWMH_CLIENT_SOURCE_TYPE_OTHER, \
+ XCB_EWMH_MOVERESIZE_WINDOW_X | XCB_EWMH_MOVERESIZE_WINDOW_Y | XCB_MOVERESIZE_WINDOW_WIDTH | XCB_MOVERESIZE_WINDOW_HEIGHT, \
+ geom.x(), geom.y(), geom.width(), geom.height());*/
+
+ //Use the basic XCB functions instead of ewmh (Issues with combining the XCB_EWMH_MOVERESIZE _*flags)
+ uint32_t values[4];
+ values[0] = geom.x(); values[1] = geom.y();
+ values[2] = geom.width(); values[3] = geom.height();
+ xcb_configure_window(QX11Info::connection(), win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
+
+}
+
// === SetScreenWorkArea() ===
/*void LXCB::SetScreenWorkArea(unsigned int screen, QRect rect){
//This is only useful because Fluxbox does not set the _NET_WORKAREA root atom
diff --git a/libLumina/LuminaX11.h b/libLumina/LuminaX11.h
index 6e229729..df32cc1c 100644
--- a/libLumina/LuminaX11.h
+++ b/libLumina/LuminaX11.h
@@ -126,11 +126,12 @@ public:
unsigned int CurrentWorkspace();
//Session Modification
-
+ void RegisterVirtualRoots(QList<WId> roots);
//Window Information
QString WindowClass(WId);
- unsigned int WindowWorkspace(WId);
+ unsigned int WindowWorkspace(WId); //The workspace the window is on
+ QRect WindowGeometry(WId, bool includeFrame = true); //the geometry of the window (frame excluded)
WINDOWSTATE WindowState(WId win); //Visible state of window
QString WindowVisibleIconName(WId win); //_WM_VISIBLE_ICON_NAME
QString WindowIconName(WId win); //_WM_ICON_NAME
@@ -140,6 +141,10 @@ public:
//Window Modification
void SetAsSticky(WId); //Stick to all workspaces
void CloseWindow(WId); //request that the window be closed
+ void MinimizeWindow(WId); //request that the window be unmapped/minimized
+ void ActivateWindow(WId); //request that the window become active
+ void MaximizeWindow(WId); //request that the window become maximized
+ void MoveResizeWindow(WId win, QRect geom);
};
bgstack15