Removing borders and frames from application windows

I'm looking for a window that has border or frame so that if it's a text editor, say, then you see only the text pane, an image display only the image.

Do you mean something like this?

If so, most applications have a "Full screen" option, usually activatable either through the menus (View -> Full screen or the likes), or by pressing some keystroke (usually the F11 key). The screenshot above is of Pluma in fullscreen mode.

Yes. That's exactly what I mean but I want to specify the window dimensions -- through resize or some such. I want to have two or even three such windows on the screen.

Ideally the window menu would be accessible through a right click or hotkey when the window is in focus.

That doesn't sound so easy, though most of what you said certainly is possible.

The best tool for this job that I could find is called Devil's Pie, and it seems to have a capability to undecorate and pre-size windows according to some programmed criteria. I think this guide on the Ubuntu Community Help Wiki is one of the best resources on using devilspie -- it even has an example window settings file which undecorated certain windows (see the pidgin.ds section about 65% of the way down the article).

I hope this helps. I'd love to hear how it turns out.

I used to mess with Xlib and have some of the old code.
I have an app that draws a rectangle and resizes the window in focus to that rectangle.
But it would resize any window even desktop and panel so you would want to avoid that.
If you can code in C maybe you can find a way to blacklist desktop and panel.
Requires: libx11-dev
select-area-resize.c

#include<stdio.h>
#include<stdlib.h>
#include<X11/Xlib.h>
#include<X11/cursorfont.h>
#include<X11/Xatom.h>
#include<unistd.h>
/* select area and resize the active window
compile with:
   gcc select-area-resize.c -Wall -o select-area-resize `pkg-config --cflags --libs x11`
*/

#define _XOPEN_SOURCE 500

#define MAXSTR 1000

Display *disp;
unsigned long window;
unsigned char *prop;

void check_status(int status, unsigned long window)
{
    if (status == BadWindow) {
        printf("window id # 0x%lx does not exists!", window);
        exit(1);
    }

    if (status != Success) {
        printf("XGetWindowProperty failed!");
        exit(2);
    }
}

unsigned char* get_string_property(char* property_name)
{
    Atom actual_type, filter_atom;
    int actual_format, status;
    unsigned long nitems, bytes_after;

    filter_atom = XInternAtom(disp, property_name, True);
    status = XGetWindowProperty(disp, window, filter_atom, 0, MAXSTR, False, AnyPropertyType,
                                &actual_type, &actual_format, &nitems, &bytes_after, &prop);
    check_status(status, window);
    return prop;
}

unsigned long get_long_property(char* property_name)
{
    get_string_property(property_name);
    unsigned long long_property = prop[0] + (prop[1]<<8) + (prop[2]<<16) + (prop[3]<<24);
    return long_property;
}


int main(int argc, char** argv)
{
 /*
 * This part was copied from https://bbs.archlinux.org/viewtopic.php?pid=660547#p660547
 * which is based on scrot's main.c
 */
  XWindowAttributes xw_attrs;

  int rx = 0, ry = 0, rw = 0, rh = 0;
  int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0;
  int btn_pressed = 0, done = 0;

  XEvent ev;
  disp = XOpenDisplay(NULL);

  if(!disp)
    return EXIT_FAILURE;

  int scr = XDefaultScreen(disp);

  Window root = 0;
  root = RootWindow(disp, scr);

  Cursor cursor, cursor2;
  cursor = XCreateFontCursor(disp, XC_cross);
  cursor2 = XCreateFontCursor(disp, XC_crosshair);

  XGCValues gcval;
  gcval.foreground = XWhitePixel(disp, 0);
  gcval.function = GXxor;
  gcval.background = XBlackPixel(disp, 0);
  gcval.plane_mask = gcval.background ^ gcval.foreground;
  gcval.subwindow_mode = IncludeInferiors;
  gcval.line_width = 2;

  GC gc;
  gc = XCreateGC(disp, root,
                 GCFunction | GCForeground | GCBackground | GCSubwindowMode | GCLineWidth ,
                 &gcval);

  /* this XGrab* stuff makes XPending true ? */
  if ((XGrabPointer
       (disp, root, False,
        ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync,
        GrabModeAsync, root, cursor, CurrentTime) != GrabSuccess))
    printf("couldn't grab pointer:");

  if ((XGrabKeyboard
       (disp, root, False, GrabModeAsync, GrabModeAsync,
        CurrentTime) != GrabSuccess))
    printf("couldn't grab keyboard:");

  while (!done) {
//  while (!done && XPending(disp)) {
//    XNextEvent(disp, &ev);
    if (!XPending(disp)) { usleep(1000); continue; } // fixes the 100% CPU hog issue in original code
    if ( (XNextEvent(disp, &ev) >= 0) ) {
      switch (ev.type) {
        case MotionNotify:
        /* this case is purely for drawing rect on screen */
          if (btn_pressed) {
            if (rect_w) {
              /* re-draw the last rect to clear it */
              XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
            } else {
              /* Change the cursor to show we're selecting a region */
              XChangeActivePointerGrab(disp,
                                       ButtonMotionMask | ButtonReleaseMask,
                                       cursor2, CurrentTime);
            }
            rect_x = rx;
            rect_y = ry;
            rect_w = ev.xmotion.x - rect_x;
            rect_h = ev.xmotion.y - rect_y;

            if (rect_w < 0) {
              rect_x += rect_w;
              rect_w = 0 - rect_w;
            }
            if (rect_h < 0) {
              rect_y += rect_h;
              rect_h = 0 - rect_h;
            }
            /* draw rectangle */
            XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
            XFlush(disp);
          }
          break;
        case ButtonPress:
          btn_pressed = 1;
          rx = ev.xbutton.x;
          ry = ev.xbutton.y;
          break;
        case ButtonRelease:
          done = 1;
          break;
      }
    }
  }
  /* clear the drawn rectangle */
  if (rect_w) {
    XDrawRectangle(disp, root, gc, rect_x, rect_y, rect_w, rect_h);
    XFlush(disp);
  }
  rw = ev.xbutton.x - rx;
  rh = ev.xbutton.y - ry;
  /* cursor moves backwards */
  if (rw < 0) {
    rx += rw;
    rw = 0 - rw;
  }
  if (rh < 0) {
    ry += rh;
    rh = 0 - rh;
  }

  window = RootWindow(disp, scr);
  window = get_long_property("_NET_ACTIVE_WINDOW");
  XGetWindowAttributes(disp, window, &xw_attrs);
  XMoveResizeWindow(disp, window, rx, ry, rw, rh);
  XCloseDisplay(disp);

  return EXIT_SUCCESS;
}

Another app that moves all windows.
move-window.c

#include<stdio.h>
#include<stdlib.h>
#include<X11/Xlib.h>
#include<X11/cursorfont.h>
#include<malloc.h>
#include<unistd.h>
#include <stdbool.h>
#include <X11/extensions/XTest.h>

/* Move a window.
 Depends: lidx11-dev libxtst-dev
compile with:
   gcc move-window.c -Wall -o move-window `pkg-config --cflags --libs x11 xtst`
*/

int main(int argc, char** argv)
{
  XWindowAttributes xw_attrs;
  Window win;
  Window *root_windows;
  unsigned int mask_return;
  int i;
  int number_of_screens;
  Bool result;
  int root_x, root_y;
  int win_x, win_y;
  int rx = 0, ry = 0;
  int rect_x = 0, rect_y = 0, rect_w = 0, rect_h = 0;
  int btn_pressed = 0, done = 0;

  XEvent ev;
  Display *disp = XOpenDisplay(NULL);

  if(!disp)
    return EXIT_FAILURE;


  Window root = 0;
  number_of_screens = XScreenCount(disp);
  root_windows = malloc(sizeof(Window) * number_of_screens);
  for (i = 0; i < number_of_screens; i++) {
    root_windows[i] = XRootWindow(disp, i);
  }
  for (i = 0; i < number_of_screens; i++) {
    result = XQueryPointer(disp, root_windows[i], &root,
         &win, &root_x, &root_y, &win_x, &win_y,
         &mask_return);
    if (result == True) {
        break;
    }
  }
  if (result != True) {
     fprintf(stderr, "No mouse found.\n");
     return -1;
  }

  XGetWindowAttributes(disp, win, &xw_attrs);

  Cursor cursor;
  cursor = XCreateFontCursor(disp, XC_fleur);

  if ((XGrabPointer
       (disp, root, False,
        ButtonMotionMask | ButtonPressMask | ButtonReleaseMask, GrabModeAsync,
        GrabModeAsync, root, cursor, CurrentTime) != GrabSuccess))
    printf("couldn't grab pointer:");

  if ((XGrabKeyboard
       (disp, root, False, GrabModeAsync, GrabModeAsync,
        CurrentTime) != GrabSuccess))
    printf("couldn't grab keyboard:");

  XTestFakeButtonEvent(disp, 1, True, CurrentTime);
  XFlush(disp);

  while (!done) {
    if (!XPending(disp)) { usleep(1000); continue; } // fixes the 100% CPU hog issue
    if ( (XNextEvent(disp, &ev) >= 0) ) {
      switch (ev.type) {
        case MotionNotify:
          if (btn_pressed) {
            rect_x = rx;
            rect_y = ry;
            rect_w = ev.xmotion.x - rect_x;
            rect_h = ev.xmotion.y - rect_y;
            rect_x += rect_w;
            rect_y += rect_h;
            XMoveWindow(disp, win, rect_x - root_x + xw_attrs.x, rect_y - root_y + xw_attrs.y);
            XFlush(disp);
          }
          continue;
        case ButtonPress:
          btn_pressed = 1;
          rect_x = xw_attrs.x;
          rect_y = xw_attrs.y;
          break;
        case ButtonRelease:
          done = 1;
          break;
      }
    }
  }

  printf("x=%d\ny=%d\n", rect_x - root_x + xw_attrs.x, rect_y - root_y + xw_attrs.y);
  free(root_windows);
  XCloseDisplay(disp);

  return EXIT_SUCCESS;
}

There is this application by muktupavels that toggles window decorations.

It wouldnt be hard to change it to toggle the topmost window.

No offense @anon94368460, but I don't know exactly what is the advantage of having @BWallard write code, versus just using devilspie or similar.

No offence taken. Just an option to explore. Full control over window position and size vs scripted devilspie setup with fixed dimensions and position.

1 Like