Is there a way to make changes to the titlebar with GTK2? - ruby

I have a desktop application written in Ruby that is using GTK2. It's just a small test application to play with GTK2, but I'm having problems achieving what I want to do. Is there any way using GTK2 to get at the titlebar (apart from setting the title), specifically to either add a button to it (beside the min/max/etc, B in the below diagram) or to add an option to the menu that pops up when you click the icon on the titlebar (A in the below diagram)?
I'm thinking there might not be because GTK is meant to work with many many different window managers, but I just wondered if there was. As a side question, what event does clicking the 'cross' button fire? At the moment if the user clicks that the window disappears but the program doesn't end - I need to capture that event and quit the program.
Thanks for any help, including hitting me over the head and telling me how silly I am.

Note that this is possible in GTK 3.10 and up, by using gtk_window_set_titlebar(). It replaces the window manager's title bar with a custom one. GtkHeaderBar is a good custom title bar class to use.
You can't, however, make it look just like the window manager would, because you won't know which window manager the user is running.

No, the title bar is owned by the window manager and you will typically not have direct access to it.
When the user tries to close the window by clicking the window manager's button, the window will receive the delete event.

Related

How can I add custom menu item to window system menu under X?

I would like to add my custom command, to a window system menu (the one usually on the left top on titlebar, usually containing Minimize, Maximize and so on), and respond to it in my application.
In ms windows one can do
HMENU hMenu = GetSystemMenu(hwnd, false);
AppendMenu(hMenu, MF_STRING, ...)
Is something like this possible under X11? If not a general method maybe a solution for some specific window manager?
Ok, after your last edit, what I understand is that you want to add your custom menu to the menu that's on the window decoration, which is controlled by the Window Manager.
I don't think that's possible, although I'm not sure. I believe you should read the ICCCM and the EWMH to find if this is possible or not:
http://en.wikipedia.org/wiki/Inter-Client_Communication_Conventions_Manual
http://en.wikipedia.org/wiki/Extended_Window_Manager_Hints
Or you can send an email to wm-spec-list asking:
http://mail.gnome.org/mailman/listinfo/wm-spec-list
Also, adding an option there makes it quite hidden, doesn't it? I guess most people don't ever click that menu... I don't even think that menu exists on all the possible Window Managers. You should really try to put your menu inside your application's Window instead of the Window Manager's decoration. Some environments don't even have Window Managers: what would your users do in this case?
Note that some applications (like the Chromium browser) don't use the Window Manager decorations: they implement their own decoration, they implement their own close/maximize/minimize buttons. This way, they have complete control over all the decoration buttons and menus, but their decoration doesn't have the same "look and feel" of the rest of the desktop. You could think about doing this, but I wouldn't encourage that... You should probably put your menu somewhere else (where it's not that hidden...).
You mean you want to add your app to the system menu?
I believe most modern desktop environments implement the XDG Menu Standard:
http://standards.freedesktop.org/menu-spec/menu-spec-latest.html
You'll have to learn other standards too probably:
http://standards.freedesktop.org/
They're all somehow short, so they won't consume more than some hours to read and learn.

Accept mouse clicks without activating the application?

I am working on a utility application that controls other running applications. On certain input event my application displays a window, user can pick some operation from the window, the window disappears and control returns to the previous app. My problem is that clicking in my app’s window activates my application, thus removing focus from the previous application’s window. I can re-activate the previous application when my window closes, but I’d rather keep the original application activated all the time. Is that possible?
It's quite easy to to, just make your window an instance of NSPanel (a subclass of NSWindow), and set it as non-activating in Xcode/IB (or create it programatically, with NSNonactivatingPanelMask in the style mask).
One idea would be: while your app is running, try to keept track of the active window in the system.
After you activate your app and click the command button, restore the previous active window.
This is only an idea, I don't know how to do it on mac.

Is it possible to create a sub window which will not deactivate the parent?

Normally when creating a sub window (WS_POPUP), the child window will become activate and the parent will become deactivated. However, with menus, both remain active. At least I am assuming the menu is active, it at least has focus.
Example: Click on the file menu in notepad, the menu appears, yet the notepad window still looks active.
Is it possible to mirror this behavior with either a window style or responding to a particular message?
Thanks
Another example: Combo boxes seem to show a subwindow, yet do not deactivate the window. And you can click on that subwindow, while still maintaining an activate main window. Any ideas on how to grab the class /style of that window?
The list dropdown in a combobox is a bit of a hack, it is both a popup and a child window, I can't recommend that approach (Undocumented style combination, and IIRC, it is a bit buggy to do this with a "normal" floating window/toolbar)
This leaves you with two options:
WS_EX_NOACTIVATE (Main window will stay active, floating window is not active)
Handle activate messages (Both windows will look active)
I am surprised that creating a new popup window activates it. Normally you'd need to call SetActiveWindow. However check out WM_ACTIVATE and WM_NCACTIVATE on how to stop the window becoming deactivated.
A fact that a lot of people miss is that windows does not have a separate window manager component :- most of the window management duties are performed by each window - usually in DefWindowProc.
Most window positioning and activation / de-activation is done - ultimately - via a call to SetWindowPos - which always sends a WM_WINDOWPOSCHANGING message allowing the window to have a final say on what happens.
DefWindowProc also activate its own window in response to mouse clicks and so on.
The result of all this is, it is quite possible to create windows that never accept activation - it does require an extensive understanding of what messages and situations might have led to an activation.
Ultimately I can say that it is VERY handy to have a debugging setup configured for remote debugging - so that you can interact with your debugger without effecting the activation state of the system - and hence drop a breakpoint into the window in questions WM_ACTIVATE handler and simply debug any situation leading to an unwanted activation.
If You want to handle keyboard focus as well, it might be trickier - normally focus is given to an activated window - but again its usually the DefWindowProc responsible for assigning both. I just see it dangerous as having one window, still obviously activated, and another with focus. This will confuse any assistive software greatly.
I'd be tempted to perform a message loop level message hook - Similar to IsDialogMessage - to filter keystrokes intended for the popup window.
If you create your popup window with WS_EX_NOACTIVATE it will not be activated by user input (You could still activate it programatically) and therefore your main application window will still remain active.

Only allow one NSWindow to be selectable until action is completed (Cocoa)

I have a program with many windows open. I want all windows to be visible, but only one window can be interactable, until a certain event has occured. e.g. pressing a button.
At the moment, I can still click another window, and interact with it, how do I only allow interaction with ONE window, until a certain event occurs?
Imagine this as the program:
I want only the frontmost Window to be selectable, if I try to select any of the other windows behind it, it should not work.
Does anoybody know how to do this?
Thanks!
Michael
It sounds like you want a modal window.

Borderless Taskbar items: Using a right click menu (VB6)

Even when BorderStyle is set to 0, it is possible to force a window to show up on the taskbar either by turning on the ShowInTaskbar property or by using the windows api directly: SetWindowLong Me.hwnd, GWL_EXSTYLE, GetWindowLong(Me.hwnd, Win.GWL_EXSTYLE) Or Win.WS_EX_APPWINDOW. However, such taskbar entries lack a right-click menu in their taskbar entry. Right-clicking them does nothing instead of bringing up a context menu. Is there a way, to attach a standard or custom handler to it?
Without a hack, I think you're going to be stuck here, I'm sorry to say. When you set the VB6 borderless properties, you inherently disable the control menu. The control menu (typically activated by right-clicking the title bar of a window or left-clicking the icon in the upper left) is what's displayed when you right-click a window in the task bar.
Now, if you're in the mood to hack, you might be able to "simulate" the behavior in such a way that the user doesn't know the difference. I got the idea from this message thread on usenet.
Basically, it sounds like you may be able to hack it by using two forms. One form is minimized right away, and becomes your "stub" in the task bar. The other form is the one you're currently designing (which we'll call the "main" form). The stub form is what actually loads and displays your main form.
The stub form isn't borderless, and must not deactivate the control menu. It is positioned off screen and at the smallest possible size. You'll respond to its form-level events, and then use those to communicate the appropriate behaviors to the borderless form.
That's the general gist of the hack. If I wasn't at work right now, I'd whip up a simple VB6 project and see if I could get it to work for you.

Resources