I am trying to create a simple panel for Openbox in Arch Linux using c++, but I cannot figure out how to remove the title bar from a window.
I am creating the window with XCreateWindow(...), and that gives a window with the correct size, but it contains a title bar, and the window also opens in the top-left corner of the screen, no matter what offset coordinates I specify.
I read here that both of these problems are probably caused by the window manager (Openbox), which overrides the window attributes I specified in XCreateWindow(..., &window_attributes). This could be solved by adding window_attributes.override_redirect = True;, although this does not seem to do anything for me. When I try this I get the exact same window as before. (I did compile the file after this change.)
Also I read into the code of Tint2 (link), which is another panel for Openbox. They create a window using the following code:
XSetWindowAttributes att = { .colormap=server.colormap, .background_pixel=0, .border_pixel=0 };
p->main_win = XCreateWindow(server.dsp, server.root_win, p->posx, p->posy, p->area.width, p->area.height, 0, server.depth, InputOutput, server.visual, mask, &att);
I don't see an override_redirect anywhere in their code, so I'm not sure how they are removing the title bar.
As additional information, I thought it would be worth mentioning how I'm executing the script:
/* The c++ file is saved as 'panel.cpp' */
$ gcc panel.cpp -lX11 -o panel
$ ./panel
Also, I am running Arch Linux through VirtualBox with Windows 8 as host. I'm not sure if this changes anything, but it won't hurt to mention.
Since I found the solution, I figured I'd post the solution here if anyone else needs it.
As #JoachimPileborg mentioned, I needed to alter the Openbox settings in ~/.config/openbox/rc.xml. Inside the <applications> tag, I added the following code:
<application class="*">
<decor>no</decor>
<position force="no"></position>
</application>
The class="*" means that all applications will follow these rules, you could fill in the class name of the application instead. The <decor>no</decor> removes the title bar, and <position force="no"></position> ensures that my own script is able to handle the positioning. You could also add another <application> tag after this one to make exceptions to this rule.
Also, the window_attributes.override_redirect = True; is not needed anymore.
A more correct way is to use the Extended Window Manager Hints.
The idea is that you don't tell the window manager how to decorate or not your window, you just indicate the window type with _NET_WM_WINDOW_TYPE :
Atom window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(display, your_window, window_type,
XA_ATOM, 32, PropModeReplace, (unsigned char *) &value,1 );
"Dock" is the type for panels and taskbar. Usually they are undecorated and appear on all desktops. As written on the documentation, previously the _MOTIF_WM_HINTS property was used to define the appearance and decorations of the window. Window managers still support it, but _NET_WM_WINDOW_TYPE is prefered as it describe the function and let the window manager (and user) decide on the appearance and behavior of that type of window.
Another interesting property for a panel is _NET_WM_STRUT_PARTIAL, to "reserve" space.
Related
So, (I rewrote this since a lot of people didn't understand me. I apologize.)
I'd like to bring the window of my qt application to the very front of ALL windows on screen.
I've heard you can do this by attaching to the thread of the foreground window and then "stealing focus" aka putting yourself where that foreground window was.
(I'm using OSX, so windows.h is no option for me.)
I hope you understand now.
To bring a window to the front, ensure the window is visible, then activate the window.
As the docs state: -
Sets the top-level widget containing this widget to be the active window.
And
If you want to ensure that the window is stacked on top as well you should also call raise().
So, assuming you have a window called pWindow, you can do something like this: -
pWindow->raise();
pWindow->show();
pWindow->activateWindow();
Also note that OS X can have multiple desktops (Spaces). If you also want the window to track the user's Space when they switch between them, you can add this function to your window class: -
void MyWindow::DisplayOnAllSpaces()
{
// ensure we stay on the active desktop
WId windowObject = this->winId();
objc_object* nsviewObject = reinterpret_cast<objc_object *>(windowObject);
objc_object* nsWindowObject = objc_msgSend(nsviewObject, sel_registerName("window"));
int NSWindowCollectionBehaviorCanJoinAllSpaces = 1 << 0;
objc_msgSend(nsWindowObject, sel_registerName("setCollectionBehavior:"), NSWindowCollectionBehaviorCanJoinAllSpaces);
}
I am experimenting with some fundamental Xlib stuff. I am creating a basic window and creating an OpenGL context for it.
I am trying to prevent the user from being able to resize or manually full screen the window. I added the code:
XSizeHints hints;
hints.min_width = hints.max_width = setup.w;
hints.min_height = hints.max_height = setup.h;
XSetWMNormalHints(dpy, win, &hints);
This worked at first. However after experimenting with it I have found that it mysteriously stops working sometimes. It is not a matter of unusual window managers or anything like that, I am using the default windows manager installed with Ubuntu. What causes it to change, strangly enough, is whether or not I include this line in main:
XWindowAttributes atts;
It does not matter where I put it. At the beginning, or inside a loop, or even after the return. As long as I put that somewhere in main the hints prevent resizing (just to be clear, any name for the variable works). It does not matter if I use it at all or not, it was initially there for a call to XGetWindowAttributes. I discovered the problem when I tried moving that into a separate function call. If I take it out, the window will have a full screen button and I will be able to shrink it. I have experimented with declaring the variable other places, such as in the struct where I contain the Window and GLXContext.
What is going on here? The way I see it I either have a very subtle and unusual bug coming from my virtual machine or something weird like that, or I have missed some obvious piece of information. Can anyone shed some light on this?
Well, I have no explanation for why declaring a XWindowAttributes instance in main was making it work, but I did figure out what was wrong with my code and I was able to make it behave as expected when I made the following changes:
Do not create XSizeHints directly as shown above. Create it as follows:
XSizeHints *hints = XAllocSizeHints();
Set flags in the object specifying which variables are used:
hints->flags = PMinSize|PMaxSize;
Use XSetWMNormalHints and XSetWMSizeHints:
XSetWMNormalHints(dpy, win, hints);
XSetWMSizeHints(dpy, win, hints, PMinSize|PMaxSize);
I also put a pointer to the hints in my struct containing data about the window. All together the code above became:
XSizeHints *hints = wind->hints = XAllocSizeHints();
hints->flags = PMinSize|PMaxSize;
hints->min_width = hints->max_width = setup.w;
hints->min_height = hints->max_height = setup.h;
XSetWMNormalHints(dpy, win, hints);
XSetWMSizeHints(dpy, win, hints, PMinSize|PMaxSize);
For those that came here:
1. Communicating with the Windows Manager
It's all about convention like said at 12.3 in the "Xlib Programming Manual VOL1". Some WM will completely ignore hints like max & min size, because eg they manage Windows as Tiled Windows. So, how YOUR Window Manager will get your choices is an issue.
2. Make things in the right order.
This will perhaps answer your question : "What is going on here?"
Most difficulties with X comes from the order you make things. I encountered the same trouble as yours, and solve it because I saw I didn't follow the right process.
Chapter 12.3.1 from the "Xlib Prog Manual" says:
'Once the client has created the windows, BUT BEFORE IT MAPS THEM, it must place properties to help WM manage them effectively'
In your case, it means you cannot use XSetWM* functions AFTER your window is mapped. Some properties will have an effect, some others not, and sometimes some will be overridden with bad values.
3. The right order. (AFAIK)
a. Set an Error Handler
b. Get a Display
c. Init your Context (here GLX) & get a Visual from it.
d. set Window Attributes (events mask, ...)
e. Create your Window
e. Set WM Properties (eg your sizehints, min/max size, class, title, ...)
e.1 always init pointers you need with XAlloc* when possible
e.2 use X11r4 XSetWMProperties that will put them all at once, avoid use of deprecated functions.
e.3 XFree your 'pointers'
f. Set the Wm Protocols you are interested in (WM_DELETE_WINDOW, ...)
g. set some others properties according to your needs (eg _NET_WM_PID, ...)
h. Finally, Map your Window
4. See what happens : use xprop
xprop will report how your window is known by your Windows Manager.
If your size hints were properly set, you will see some lines like:
WM_NORMAL_HINTS(WM_SIZE_HINTS):
user specified location: 550, 200
user specified size: 500 by 500
program specified minimum size: 500 by 500
program specified maximum size: 65535 by 65535
Hope it helps future users,
(PS: the previous answer TS#Oct 27 '14 at 15:26 has an error: XSetWMSizeHints expect an Atom as 3rd arg.).
I'm writing my own class to create and handle a progress/overlayicons for a programs taskbar icon.
I'm using the ITaskbarList3 for Windows 7/higher to do this. I can now create a progress or overlayicons, but what I'm missing is the alert/blink effect, that appears if a program wants to get the users attention (e.g. if you have to confirm admin rights and are working on a different tab).
I do not mean the pause/error-indicators for a progress, I need the blinking orange effect, and i wasn't able to find something until now.
Thanks for your help.
Use FlashWindowEx function. See the doc on FLASHWINFO - you can start flashing, stop flashing and specify flashing parameters.
For continuous blinking until the user clicks on the window the code is like this:
FLASHWINFO fi;
fi.cbSize = sizeof(FLASHWINFO);
fi.hwnd = yourHwnd;
fi.dwFlags = FLASHW_ALL | FLASHW_TIMERNOFG;
fi.uCount = 0;
fi.dwTimeout = 0;
FlashWindowEx(&fi);
Using CWnd::ShowWindow(SW_SHOWMAXIMIZED) maximizes my app window as expected.
However, when clicking the restore button on the app (or double clicking the title-bar), the restored size is the same size as the maximized window, which is confusing for the user.
Using this alternative code has the same problem:
WINDOWPLACEMENT wndpl;
GetWindowPlacement(&wndpl);
wndpl.showCmd = SW_SHOWMAXIMIZED;
SetWindowPlacement(&wndpl);
How can I keep the default un-maximized size when restoring.
I've solved my problem, and the solution might solve yours too. My problem was that even though I called SetWindowPlacement(&wndpl) within CMainFrame::OnCreate the window was not properly restored if it was maximized. I added two lines of code before SetWindowPlacement, and now it works as expected.
CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
...
// Obtain wndpl, maybe from registry
AfxGetApp()->m_nCmdShow = wndpl.showCmd;
wndpl.showCmd = SW_SHOW;
SetWindowPlacement(&wndpl);
}
These two lines helps underlying code not to mess things up when calling ActivateFrame, which calls ShowWindow with parameter obtained from CWinApp::m_nCmdShow.
All information are in the file with extension .RC. I never used a Maximize/Restore procedures though you should look for a 'DIALOGEX' for the same window. You can change it using any editor (notepad, ultraedit etc.)
How do I create a Motif main window that doesn't have a system menu, minimize and maximize boxes? I just cannot find out how by googling and reading docs and tutorials. I believe that it should be possible with some additional parameters for XtVaCreateManagedWindow, but which?
I have tried several variants of XtVaSetValues (topWid, XmNmwmDecorations, ...) but none worked. Instead I get an error message that I need to use a vendor shell for this. Most widget types aren't derived from vendor shells however, and when I e.g. try to use a dialog shell and put a scrollable text widget inside of it, then then text widget seems to control the dialog.
Apparently it's not (easily) possible to get rid of the window (system) menu, but it seems to be possible to disable window menu items with some code like this:
int i;
XtVaGetValues (widget, XmNmwmFunctions, &i);
i &= ~(MWM_FUNC_ALL | MWM_FUNC_MINIMIZE | MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE);
XtVaSetValues (widget, XmNmwmFunctions, i);
which removes the related window decoration too and apparently even works for non vendor shell widgets.
There should also be the possibility to remove the decorations (i.e. make them invisible). However, please note that these "system menu" decorations belong to the Window Manager, not your Motif program itself. It is up to the Window Manager to handle your requests or disregard them--you might get vendor-specific behavior with any MWM resources.
Anyway, here's the code sample to try out:
int decors; //bit-mask of flags defining the decorations, from Xm/MwmUtil.h
XtVaGetValues(dlg, XmNmwmDecorations, &decors, NULL);
decors &= ~MWM_DECOR_MENU;
decors &= ~MWM_DECOR_MAXIMIZE;
decors &= ~MWM_DECOR_MINIMIZE;
XtVaSetValues(dlg, XmNmwmDecorations, decors, NULL);
If you intend to run your application from Mwm, you can achieve the desired behavior by setting (e.g. via XtVaAppInitialize()) the following X11 resources:
! Title bar buttons
Mwm*YourApplicationClassHere.clientDecoration: -minimize -maximize
! Window menu functions
Mwm*YourApplicationClassHere.clientFunctions: -minimize -maximize
These resources are explained in more detail here and here.
Speaking of window menu, this one depends on a specific window manager in use. Mwm, for instance, allows the client to set the menu name using Mwm*YourApplicationClassHere.windowMenu resource, the menu itself must be defined in either ${HOME}/.mwmrc or global mwmrc, or XmNmwmMenu resource of VendorShell. The resulting custom window menu is exposed as a _MOTIF_WM_MENU atom, which seems to be ignored by modern window managers.
Sample mwmrc menu definitions may look like this
Menu CustomMenu0
{
Restore _R Alt<Key>F5 f.restore
Move _M Alt<Key>F7 f.move
Size _S Alt<Key>F8 f.resize
Minimize _n Alt<Key>F9 f.minimize
Maximize _x Alt<Key>F10 f.maximize
Lower _L Alt<Key>F3 f.lower
no-label f.separator
Pass\ Keys _K f.pass_keys
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
Menu CustomMenu1
{
Your\ Application\ Name\ Here f.title
no-label f.separator
Close _C Alt<Key>F4 f.kill
}
(see the function descriptions). Custom menu items can be added using f.send_msg (examples here and here).
I'm pretty sure all of the above also applies to Dtwm (CDE).