Re: Implement WM hints spec (bug 50079)



Alexander Larsson <alla lysator liu se> writes: 
> typedef enum
> {
>  GDK_WINDOW_STATE_HINT_MODAL                = 1<<0,
>  GDK_WINDOW_STATE_HINT_STICKY               = 1<<1,
>  GDK_WINDOW_STATE_HINT_MAXIMIZED_VERTICAL   = 1<<2,
>  GDK_WINDOW_STATE_HINT_MAXIMIZED_HORIZONTAL = 1<<3,
>  GDK_WINDOW_STATE_HINT_SHADED               = 1<<4,
>  GDK_WINDOW_STATE_HINT_SKIP_TASKBAR         = 1<<5,
>  GDK_WINDOW_STATE_HINT_SKIP_PAGER           = 1<<6
> } GdkWindowStateHint;
> 

Planning gtk_window_present(), gtk_window_iconify(), and signals on
(de)iconification turns out to be relevant to this. 

I did an initial implementation which turned out to be a bit wrong, so
replacing it with something like this:

typedef enum
{
  GDK_WINDOW_STATE_WITHDRAWN,
  GDK_WINDOW_STATE_NORMAL,
  GDK_WINDOW_STATE_ICONIFIED
} GdkWindowState;

void gdk_window_request_state (GdkWindow *window, GdkWindowState state);

gdk_window_show() becomes gdk_window_request_state(NORMAL) +
gdk_window_raise().

gdk_window_withdraw() becomes gdk_window_request_state(WITHDRAWN).

gdk_window_hide() isn't supposed to be used on toplevel windows.

We also have:
  struct _GdkEventWindowStateChange
  {
    GdkEventType type;
    GdkWindow *window;
    gint8 send_event;
    GdkWindowState new_state;
  };

In System.WinForms (win32), the 3 window states are normal, minimized,
and maximized; so that's an argument for adding
GDK_WINDOW_STATE_MAXIMIZED.

SHADED, MAXIMIZED_VERTICAL, and MAXIMIZED_HORIZONTAL make sense to me
also (but note that maximized vertical/horizontal are not the same as
in the WM spec, here they are mutually exclusive with plain
_MAXIMIZED, since a window has a single state not a set of flags).

MODAL, STICKY, SKIP_TASKBAR, and SKIP_PAGER seem like totally
unrelated hints - perhaps we should lump these in to an existing GDK
hints-setting function? Actually I think simply
gdk_window_set_sticky(), gdk_window_set_skip_taskbar(),
gdk_window_set_skip_pager() would be more intuitive. For the modal
hint, gdk_window_set_modal() strikes me as confusing since this hint
is kind of an FYI for the window manager, rather than actually
implementing modality, while e.g. set_sticky() actually makes the
window sticky. Unless I'm totally wrong about that.

Anyway, if MODAL is just a hint to the WM to maybe display things
differently, I would suggest adding it to the window type hint:
 typedef enum
 {
  GDK_WINDOW_TYPE_HINT_NORMAL,
  GDK_WINDOW_TYPE_HINT_DIALOG,
+ GDK_WINDOW_TYPE_HINT_MODAL_DIALOG,
  GDK_WINDOW_TYPE_HINT_MENU,
  GDK_WINDOW_TYPE_HINT_TOOLBAR,
  GDK_WINDOW_TYPE_HINT_DOCK,
  GDK_WINDOW_TYPE_HINT_DESKTOP
 } GdkWindowTypeHint;

It seems to make sense there to me. So this GDK function would
sometimes use the WM spec and sometimes not.

In general I think we want an API that makes sense, i.e. the way we
want to implement the hints spec is to export API that happens to use
it but makes sense independently, and can also be implemented on
Windows and framebuffer and so on in a sane way. The WM spec is not
really designed to be a beautiful API.

We should coordinate efforts, how about I do the GDK_WINDOW_STATE
thing and the StateChanged event, since I have that half-done - if you
want to do the window type hints (and make GTK use the GDK feature,
e.g. in gtkdialog.c) I'll stay out of your way. Also I don't plan to
go through the WM spec exhaustively in the near future; we should at
least make a list of all features that we think should be exported
from GDK in some way and add a comment to bugzilla with that list.

BTW I've stubbed out this function and will check it in tomorrow
hopefully:
 
gboolean
_gdk_wmspec_supported (GdkAtom property)
{

  /* FIXME FIXME */
  return FALSE;
}

This will indicate whether a given WM spec feature is supported, for
cases where we have a fallback implementation, e.g. I just added this:
 
void
gdk_window_focus (GdkWindow *window,
                  guint32    timestamp)
{
  g_return_if_fail (GDK_IS_WINDOW (window));

  if (GDK_WINDOW_DESTROYED (window))
    return;
  
  if (_gdk_wmspec_supported (gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
    {
      XEvent xev;

      xev.xclient.type = ClientMessage;
      xev.xclient.serial = 0;
      xev.xclient.send_event = True;
      xev.xclient.window = gdk_root_window;
      xev.xclient.display = gdk_display;
      xev.xclient.window = gdk_root_window;
      xev.xclient.message_type = gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE);
      xev.xclient.format = 32;
      xev.xclient.data.l[0] = 0;
      
      XSendEvent (gdk_display, gdk_root_window, False,
                  SubstructureRedirectMask | SubstructureNotifyMask,
                  &xev);
    }
  else
    {
      XSetInputFocus (GDK_DISPLAY (),
                      GDK_WINDOW_XWINDOW (window),
                      RevertToNone,
                      timestamp);
    }
}

So to implement _gdk_wmspec_supported() we have to look at the
_NET_SUPPORTED property, and also track DestroyNotify on the
_NET_SUPPORTING_WM_CHECK window in case our WM changes or goes
away. Anyway, assume this function exists, at some point it will get
implemented.

Havoc









[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]