Xfce Forum

Sub domains
 

You are not logged in.

#1 2021-09-17 14:11:40

Iago
Member
Registered: 2021-09-17
Posts: 1

Weird behaviour using Alt+Tab with LibreOffice. Is it an XFCE bug?

Hi!

I am new to this forum. I just found a weird behaviour which seems to me related to XFCE, but as other software is related I would not say 100% sure that it is an XFCE bug.

I am using Debian 11 with updated packages and, in particular, XFCE 4.16. I use often the shortcut Alt+Tab to switch among windows in a workspace, usually without problems.

The weird behaviour is when using LibreOffice Calc (I tested with versions 7.0.4.2 and 7.1.4.2). If I have the cursor on a cell, Alt+Tab seems to work fine, but if I place the cursor on the Find  toolbar (by means of the touchpad or Ctrl+F), when next I use Alt+Tab to switch to another window, then in an abstract way the switch is done (sometimes)*, but the window in front is still LibreOffice Calc.

* I say that in an abstract way the switch is done (sometimes) because:

  • First, on the panel bar, among the shown tabs of open windows, the app marked is that I decided to switch with Alt+Tab (sometimes)

  • Moreover, after I have done the previous step, so 1) I was on LibreOffice Calc on Find Toolbar, but after 2) I switched window with Alt+Tab but I see yet LibreOffice Calc window, then, if 3) I use again Alt+Tab, this time the window that appears is the one I decide, so it works fine.

  • That happens sometimes, but other times, after using Alt+Tab to swich to another window, the app marked on the panel  bar is yet LibreOffice Calc

NB: I tried to illustrate the first item of the list with an screenshot saved on Dropbox, but I couldn't get it previewed on this message. Let me know if I could be more specific, or if this issue happens also to you.

Thank you!


Iago

Last edited by Iago (2021-09-17 14:17:55)

Offline

#2 2021-09-17 20:02:00

ToZ
Administrator
From: Canada
Registered: 2011-06-02
Posts: 11,993

Re: Weird behaviour using Alt+Tab with LibreOffice. Is it an XFCE bug?

Hello and welcome.

I can replicate this on my system as well. I'm not sure if this is a bug in xfwm4 or the libreoffice find dialog somehow interfering in the process. I'm leaning towards libreoffice as I can't replicate the problem with other find dialogs in the system.


Mark solved threads as [SOLVED] to make it easier for others to find solutions.
--- How To Ask For Help | FAQ | Developer Wiki  |  Community | Contribute ---

Offline

#3 2025-05-26 13:46:28

xfce-amateur
Member
Registered: 2021-06-23
Posts: 12
LinuxFirefox 128.0

Re: Weird behaviour using Alt+Tab with LibreOffice. Is it an XFCE bug?

I can replicate this.

The LO community has been aware of this for a while:
https://bugs.documentfoundation.org/sho … ?id=156232

Reported to XFWM devs today:
https://gitlab.xfce.org/xfce/xfwm4/-/issues/863

Last edited by xfce-amateur (2025-05-26 13:47:01)

Offline

#4 2025-06-03 17:30:39

Misko_2083
Member
Registered: 2015-10-13
Posts: 223
Website
LinuxFirefox 128.0

Re: Weird behaviour using Alt+Tab with LibreOffice. Is it an XFCE bug?

I have a workaround for this, a small app in C that monitors focus changes and raises the new active window when focus leaves a LibreOffice window,
ensuring the selected application comes to the top of the stacking order.

Requires libx11-dev

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

/* Compilation and execution instructions:
 *   gcc -o lo-focus-tracker lo_focus_tracker.c -lX11
 *   ./lo-focus-tracker 
 */

/* Error handler to ignore BadWindow errors and prevent crashes */
int ignore_xerror(Display *dpy, XErrorEvent *error) {
    if (error->error_code == BadWindow) {
        return 0;  // Silently ignore BadWindow errors (e.g., when a window is closed)
    }
    return 0;
}

/* Check if a window belongs to LibreOffice by inspecting its WM_CLASS */
bool is_libreoffice(Display *dpy, Window win) {
    if (!win || win == None) return false;  // Invalid or null window

    XClassHint class_hint;
    if (XGetClassHint(dpy, win, &class_hint)) {  // Retrieve window's class hint
        bool result = false;
        if (class_hint.res_class) {
            // Check if "libreoffice" is in the window's class name
            result = strstr(class_hint.res_class, "libreoffice") != NULL;
        }
        // Free allocated memory for class hint
        if (class_hint.res_name) XFree(class_hint.res_name);
        if (class_hint.res_class) XFree(class_hint.res_class);
        return result;
    }
    return false;  // Failed to get class hint
}

/* Check if a window is minimized by inspecting _NET_WM_STATE */
bool is_minimized(Display *dpy, Window win) {
    if (!win || win == None) return false;  // Invalid or null window

    // Get atoms for _NET_WM_STATE and _NET_WM_STATE_HIDDEN
    Atom _NET_WM_STATE = XInternAtom(dpy, "_NET_WM_STATE", True);
    Atom HIDDEN = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", True);

    Atom actual_type;
    int format;
    unsigned long nitems, bytes;
    unsigned char *data = NULL;

    // Retrieve window's _NET_WM_STATE property
    if (XGetWindowProperty(dpy, win, _NET_WM_STATE, 0, (~0L), False,
                           XA_ATOM, &actual_type, &format, &nitems, &bytes, &data) == Success) {
        if (data) {
            Atom *atoms = (Atom *)data;
            // Check if _NET_WM_STATE_HIDDEN is present
            for (unsigned long i = 0; i < nitems; i++) {
                if (atoms[i] == HIDDEN) {
                    XFree(data);
                    return true;  // Window is minimized
                }
            }
            XFree(data);  // Free property data
        }
    }
    return false;  // Window is not minimized
}

/* Get the currently active window using _NET_ACTIVE_WINDOW */
Window get_active_window(Display *dpy) {
    Atom actual_type;
    int format;
    unsigned long nitems, bytes;
    unsigned char *data = NULL;
    // Get atom for _NET_ACTIVE_WINDOW
    Atom _NET_ACTIVE_WINDOW = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", True);

    // Retrieve _NET_ACTIVE_WINDOW property from the root window
    if (XGetWindowProperty(dpy, DefaultRootWindow(dpy),
                           _NET_ACTIVE_WINDOW, 0, (~0L), False, AnyPropertyType,
                           &actual_type, &format, &nitems, &bytes, &data) == Success) {
        if (nitems > 0 && data != NULL) {
            Window win = *(Window *)data;  // Extract window ID
            XFree(data);  // Free property data
            return win;
        }
    }
    return None;  // No active window found
}

/* Main program to monitor focus changes and raise new active windows */
int main() {
    // Open connection to the X11 display
    Display *dpy = XOpenDisplay(NULL);
    if (!dpy) {
        fprintf(stderr, "Cannot open display\n");
        return 1;  // Exit if display cannot be opened
    }

    // Set error handler to prevent crashes
    XSetErrorHandler(ignore_xerror);

    Window prev_active = None;  // Track previously active window

    // Main loop to monitor active window changes
    while (1) {
        Window current = get_active_window(dpy);  // Get current active window

        // Check if the active window has changed
        if (current != prev_active) {
            // Determine if current and previous windows are LibreOffice
            bool current_is_lo = is_libreoffice(dpy, current);
            bool prev_is_lo = (prev_active != None) && is_libreoffice(dpy, prev_active);
            bool prev_is_minimized = (prev_active != None) && is_minimized(dpy, prev_active);

            // Handle focus loss from a non-minimized LibreOffice window
            if (prev_is_lo && !prev_is_minimized && current != prev_active) {
                // Log focus change for debugging
                printf("LibreOffice focus lost: 0x%lx → 0x%lx\n", prev_active, current);

                // Optional: Uncomment to show a notification (requires notify-send)
                //system("notify-send 'LibreOffice focus lost'");

                // Workaround for xfwm4: Raise the new active window
                if (current != None) {
                    XRaiseWindow(dpy, current);  // Bring new window to the top
                    XFlush(dpy);  // Ensure the raise command is sent
                }
            }

            prev_active = current;  // Update previous window
        }

        usleep(300000);  // Sleep for 0.3 seconds to reduce CPU usage
    }

    // Close the display connection
    XCloseDisplay(dpy);
    return 0;
}

If you prefer this is a bash version which requires xdotool

#!/bin/bash

# Script to monitor LibreOffice window focus changes and ensure proper window activation
# Workaround for xfwm4 window cycling issue with LibreOffice (Xfce GitLab issue #864)
# Uses xdotool to track and activate windows when focus leaves or switches LibreOffice windows

# Initialize variables to track previous state
PREV_LO_WINDOW=""       # ID of the previously focused LibreOffice window
PREV_LO_APP=""          # Application name of the previous LibreOffice window
PREV_IN_FOCUS=false     # Flag indicating if a LibreOffice window was last in focus

# Function to extract the LibreOffice application name from a window's WM_NAME
# Args:
#   $1: Window ID
# Returns: The first word of the WM_NAME property (e.g., "Writer", "Calc")
get_lo_app_name() {
    local win_id=$1
    # Use xprop to get WM_NAME, extract the string, and take the first word
    xprop -id "$win_id" WM_NAME 2>/dev/null | sed -n 's/.*= "\(.*\)".*/\1/p' | awk '{print $1}'
}

# Main loop to monitor window focus changes
while :
do
    # Get the currently active and focused windows using xdotool
    ACTIVE_WIN=$(xdotool getactivewindow 2>/dev/null)  # ID of the active window
    FOCUS_WIN=$(xdotool getwindowfocus 2>/dev/null)    # ID of the focused window
    # Get all visible LibreOffice windows (based on WM_CLASS "libreoffice")
    LO_WINDOWS=$(xdotool search --onlyvisible --class libreoffice 2>/dev/null)

    # Log current state for debugging
    echo "-----------------------------"
    printf "Active: 0x%08x\n" "$ACTIVE_WIN"  # Print active window ID in hex
    printf "Focus:  0x%08x\n" "$FOCUS_WIN"   # Print focused window ID in hex

    # Initialize variables for the current LibreOffice window
    CURRENT_LO_WINDOW=""  # ID of the current LibreOffice window (if any)
    CURRENT_LO_APP=""     # Application name of the current LibreOffice window

    # Check if any LibreOffice window is active or focused
    for win in $LO_WINDOWS; do
        if [[ "$win" == "$ACTIVE_WIN" || "$win" == "$FOCUS_WIN" ]]; then
            CURRENT_LO_WINDOW="$win"                    # Store matching window ID
            CURRENT_LO_APP=$(get_lo_app_name "$win")    # Get its application name
            break  # Exit loop after finding the first match
        fi
    done

    # Handle focus transitions
    if [ -n "$CURRENT_LO_WINDOW" ]; then
        # A LibreOffice window is active or focused
        if $PREV_IN_FOCUS && [ "$CURRENT_LO_WINDOW" != "$PREV_LO_WINDOW" ]; then
            # Focus switched from one LibreOffice window to another
            # Activate the new LibreOffice window to ensure it’s raised
            xdotool windowactivate "$CURRENT_LO_WINDOW"
            echo "Activated new LO window: 0x$CURRENT_LO_WINDOW"
        fi
        # Update state for the next iteration
        PREV_IN_FOCUS=true
        PREV_LO_WINDOW="$CURRENT_LO_WINDOW"
        PREV_LO_APP="$CURRENT_LO_APP"
    else
        # No LibreOffice window is active or focused
        if $PREV_IN_FOCUS; then
            # Focus left a LibreOffice window; activate the new active window
            xdotool windowactivate "$ACTIVE_WIN"
            echo "Activated non-LO window: 0x$ACTIVE_WIN"
        fi
        # Reset state for non-LibreOffice focus
        PREV_IN_FOCUS=false
        PREV_LO_WINDOW=""
        PREV_LO_APP=""
    fi

    # Print a blank line for readability
    echo ""
    # Sleep for 1 second to reduce CPU usage
    sleep 1
done

While one of these is running it will raise the selected window on Alt+TAB even though find is open in Libre Office apps (e.g Writter, Calc).

Last edited by Misko_2083 (2025-06-03 17:34:49)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

Registered users online in this topic: 0, guests: 1
[Bot] ClaudeBot

Board footer

Powered by FluxBB
Modified by Visman

[ Generated in 0.013 seconds, 7 queries executed - Memory usage: 584.05 KiB (Peak: 600.89 KiB) ]