示例#1
0
文件: main.c 项目: kcirick/fusionwm
// event handler implementations 
void configurerequest(XEvent* event) {
   XConfigureRequestEvent* cre = &event->xconfigurerequest;
   Client* client = get_client_from_window(cre->window);
   if (client) {
      XConfigureEvent ce;
      ce.type = ConfigureNotify;
      ce.display = gDisplay;
      ce.event = cre->window;
      ce.window = cre->window;
      ce.x = client->last_size.x;
      ce.y = client->last_size.y;
      ce.width = client->last_size.width;
      ce.height = client->last_size.height;
      ce.override_redirect = False;
      ce.border_width = cre->border_width;
      ce.above = cre->above;
      XSendEvent(gDisplay, cre->window, False, StructureNotifyMask, (XEvent*)&ce);
   } else {
      // if client not known.. then allow configure.
      // its probably a nice conky or dzen2 bar :)
      XWindowChanges wc;
      wc.x = cre->x;
      wc.y = cre->y;
      wc.width = cre->width;
      wc.height = cre->height;
      wc.border_width = cre->border_width;
      wc.sibling = cre->above;
      wc.stack_mode = cre->detail;
      XConfigureWindow(gDisplay, cre->window, cre->value_mask, &wc);
   }
}
示例#2
0
void set_floating(const Arg *arg){
   Window win = frame_focused_window(g_cur_frame);
   if (!win) return;
   Client *client = get_client_from_window(win);
   if (!client) return;

   client_set_floating(client, !client->floating);
}
示例#3
0
void window_focus(Window window) {
    window_unfocus(lastfocus);
    XSetWindowBorder(gDisplay, window, wincolors[1][ColWindowBorder]);
    if(!get_client_from_window(window)->neverfocus)
      XSetInputFocus(gDisplay, window, RevertToPointerRoot, CurrentTime);

    lastfocus = window;
}
示例#4
0
文件: main.c 项目: kcirick/fusionwm
void mapnotify(XEvent* event) {
   Client* c;
   if ((c = get_client_from_window(event->xmap.window))) {
      // reset focus. so a new window gets the focus if it shall have the input focus
      frame_focus_recursive(g_cur_frame);
      // also update the window title - just to be sure
      client_update_title(c);
   }
}
示例#5
0
void mouse_handle_event(XEvent* ev) {
    XButtonEvent* be = &(ev->xbutton);
    MouseBinding* b = mouse_binding_find(be->state, be->button);
    HSClient* client = get_client_from_window(ev->xbutton.window);
    if (!b || !client) {
        // there is no valid bind for this type of mouse event
        return;
    }
    b->action(client, b->argc, b->argv);
}
示例#6
0
文件: clientlist.c 项目: xiaq/hlwm
void window_focus(Window window) {
    HSClient* client = get_client_from_window(window);
    assert(client != NULL);
    // set keyboard focus
    if (!client->neverfocus) {
        XSetInputFocus(g_display, window, RevertToPointerRoot, CurrentTime);
    }
    else client_sendevent(client, g_wmatom[WMTakeFocus]);

    if (window != lastfocus) {
        /* FIXME: this is a workaround because window_focus always is called
         * twice.  see BUGS for more information
         *
         * only emit the hook if the focus *really* changes */
        // unfocus last one
        window_unfocus(lastfocus);
        hsobject_link(g_client_object, &client->object, "focus");
        ewmh_update_active_window(window);
        tag_update_each_focus_layer();
        char* title = client ? client->title->str : "?";
        char winid_str[STRING_BUF_SIZE];
        snprintf(winid_str, STRING_BUF_SIZE, "0x%x", (unsigned int)window);
        hook_emit_list("focus_changed", winid_str, title, NULL);
    }

    // change window-colors
    HSDebug("window_focus ACTIVE\n");
    window_update_border(window, g_window_border_active_color);

    lastfocus = window;
    /* do some specials for the max layout */
    bool is_max_layout = frame_focused_window(g_cur_frame) == window
                         && g_cur_frame->content.clients.layout == LAYOUT_MAX
                         && get_current_monitor()->tag->floating == false;
    if (*g_raise_on_focus || is_max_layout) {
        client_raise(client);
    }
    tag_update_focus_layer(get_current_monitor()->tag);
    grab_client_buttons(get_client_from_window(window), true);
    client_set_urgent(client, false);
}
示例#7
0
文件: clientlist.c 项目: xiaq/hlwm
void window_unfocus(Window window) {
    HSDebug("window_unfocus NORMAL\n");
    window_update_border(window, g_window_border_normal_color);
    HSClient* c = get_client_from_window(window);
    if (c) {
        if (c->urgent) {
            HSDebug("window_unfocus URGENT\n");
            window_update_border(window, g_window_border_urgent_color);
        }
        grab_client_buttons(c, false);
    }
}
示例#8
0
文件: clientlist.c 项目: xiaq/hlwm
/**
 * \brief   Resolve a window description to a client or a window id
 *
 * \param   str     Describes the window: "" means the focused one, "urgent"
 *                  resolves to a arbitrary urgent window, "0x..." just
 *                  resolves to the given window.
 * \param   ret_client  The client pointer is stored there if ret_client is
 *                      given and the specified window is managed.
 * \return          The resolved window id is stored there if the according
 *                  window has been found
 */
Window string_to_client(char* str, HSClient** ret_client) {
    Window win = 0;
    if (!strcmp(str, "")) {
        win = frame_focused_window(g_cur_frame);
        if (ret_client) {
            *ret_client = get_client_from_window(win);
        }
    } else if (!strcmp(str, "urgent")) {
        HSClient* client = get_urgent_client();
        if (client) {
            win = client->window;
        }
        if (ret_client) {
            *ret_client = client;
        }
    } else if (1 == sscanf(str, "0x%lx", (long unsigned int*)&win)) {
        if (ret_client) {
            *ret_client = get_client_from_window(win);
        }
    }
    return win;
}
示例#9
0
Client* manage_client(Window win) {
   if (get_client_from_window(win)) return NULL;

   // init client
   Client* client = create_client();
   Monitor* m = get_current_monitor();
   // set to window properties
   client->window = win;
   client_update_title(client);

   // apply rules
   int manage = 1;
   rules_apply(client, &manage);
   if (!manage) {
      destroy_client(client);
      // map it... just to be sure
      XMapWindow(gDisplay, win);
      return NULL;
   }

   unsigned int border, depth;
   Window root_win;
   int x, y;
   unsigned int w, h;
   XGetGeometry(gDisplay, win, &root_win, &x, &y, &w, &h, &border, &depth);
   // treat wanted coordinates as floating coords
   XRectangle size = client->float_size;
   size.width = w;
   size.height = h;
   size.x = m->rect.x + m->rect.width/2 - size.width/2;
   size.y = m->rect.y + m->rect.height/2 - size.height/2 + bar_height;
   client->float_size = size;
   client->last_size = size;
   XMoveResizeWindow(gDisplay, client->window, size.x, size.y, size.width, size.height);

   // actually manage it
   g_array_append_val(g_clients, client);
   XSetWindowBorderWidth(gDisplay, win, window_border_width);
   // insert to layout
   if (!client->tag)   client->tag = m->tag;

   // get events from window
   client_update_wm_hints(client);
   XSelectInput(gDisplay, win, CLIENT_EVENT_MASK);
   window_grab_button(win);
   frame_insert_window(client->tag->frame, win);
   monitor_apply_layout(find_monitor_with_tag(client->tag));

   return client;
}
示例#10
0
文件: main.c 项目: xiaq/hlwm
void event_on_configure(XEvent event) {
    XConfigureRequestEvent* cre = &event.xconfigurerequest;
    HSClient* client = get_client_from_window(cre->window);
    XConfigureEvent ce;
    ce.type = ConfigureNotify;
    ce.display = g_display;
    ce.event = cre->window;
    ce.window = cre->window;
    if (client) {
        bool changes = false;
        if (client->sizehints && !client->dragged) {
            cre->width += 2*cre->border_width - 2*client->last_border_width;
            cre->height += 2*cre->border_width - 2*client->last_border_width;
            if (client->float_size.width != cre->width) changes = true;
            if (client->float_size.height != cre->height) changes = true;
            client->float_size.width = cre->width;
            client->float_size.height = cre->height;
            ce.x = client->last_size.x;
            ce.y = client->last_size.y;
            ce.width = client->last_size.width;
            ce.height = client->last_size.height;
            ce.override_redirect = False;
            ce.border_width = cre->border_width;
            ce.above = cre->above;
        }
        if (changes && client->tag->floating) {
            client_resize_floating(client, find_monitor_with_tag(client->tag));
        } else if (changes && client->pseudotile) {
            monitor_apply_layout(find_monitor_with_tag(client->tag));
        } else {
        // FIXME: why send event and not XConfigureWindow or XMoveResizeWindow??
            XSendEvent(g_display, cre->window, False, StructureNotifyMask,
                       (XEvent*)&ce);
        }
    } else {
        // if client not known.. then allow configure.
        // its probably a nice conky or dzen2 bar :)
        XWindowChanges wc;
        wc.x = cre->x;
        wc.y = cre->y;
        wc.width = cre->width;
        wc.height = cre->height;
        wc.border_width = cre->border_width;
        wc.sibling = cre->above;
        wc.stack_mode = cre->detail;
        XConfigureWindow(g_display, cre->window, cre->value_mask, &wc);
    }
}
示例#11
0
文件: main.c 项目: kcirick/fusionwm
void maprequest(XEvent* event) {
    XMapRequestEvent* mapreq = &event->xmaprequest;
    Client *c;

    if((c = wintosystrayicon(mapreq->window))) {
       resizebarwin(get_current_monitor());
       updatesystray();
    }

    if (!get_client_from_window(mapreq->window)) {
        // client should be managed (is not ignored but is not managed yet
        Client* client = manage_client(mapreq->window);
        if (client && find_monitor_with_tag(client->tag)) 
            XMapWindow(gDisplay, mapreq->window);
    } 
}
示例#12
0
文件: main.c 项目: xiaq/hlwm
void buttonpress(XEvent* event) {
    XButtonEvent* be = &(event->xbutton);
    HSDebug("name is: ButtonPress on sub %lx, win %lx\n", be->subwindow, be->window);
    if (mouse_binding_find(be->state, be->button)) {
        mouse_start_drag(event);
    } else {
        focus_window(be->window, false, true);
        if (*g_raise_on_click) {
            HSClient* client = get_client_from_window(be->window);
            if (client) {
                client_raise(client);
            }
        }
    }
    XAllowEvents(g_display, ReplayPointer, be->time);
}
示例#13
0
void event_on_configure(XEvent event) {
    XConfigureRequestEvent* cre = &event.xconfigurerequest;
    HSClient* client = get_client_from_window(cre->window);
    if (client) {
        bool changes = false;
        Rectangle newRect = client->float_size;
        if (client->sizehints_floating &&
            (is_client_floated(client) || client->pseudotile))
        {
            bool width_requested = 0 != (cre->value_mask & CWWidth);
            bool height_requested = 0 != (cre->value_mask & CWHeight);
            bool x_requested = 0 != (cre->value_mask & CWX);
            bool y_requested = 0 != (cre->value_mask & CWY);
            cre->width += 2*cre->border_width;
            cre->height += 2*cre->border_width;
            if (width_requested && newRect.width  != cre->width) changes = true;
            if (height_requested && newRect.height != cre->height) changes = true;
            if (x_requested || y_requested) changes = true;
            if (x_requested) newRect.x = cre->x;
            if (y_requested) newRect.y = cre->y;
            if (width_requested) newRect.width = cre->width;
            if (height_requested) newRect.height = cre->height;
        }
        if (changes && is_client_floated(client)) {
            client->float_size = newRect;
            client_resize_floating(client, find_monitor_with_tag(client->tag));
        } else if (changes && client->pseudotile) {
            client->float_size = newRect;
            monitor_apply_layout(find_monitor_with_tag(client->tag));
        } else {
        // FIXME: why send event and not XConfigureWindow or XMoveResizeWindow??
            client_send_configure(client);
        }
    } else {
        // if client not known.. then allow configure.
        // its probably a nice conky or dzen2 bar :)
        XWindowChanges wc;
        wc.x = cre->x;
        wc.y = cre->y;
        wc.width = cre->width;
        wc.height = cre->height;
        wc.border_width = cre->border_width;
        wc.sibling = cre->above;
        wc.stack_mode = cre->detail;
        XConfigureWindow(g_display, cre->window, cre->value_mask, &wc);
    }
}
示例#14
0
void unmanage_client(Window win) {
   Client* client = get_client_from_window(win);
   if (!client)   return;

   // remove from tag
   frame_remove_window(client->tag->frame, win);
   // and arrange monitor
   Monitor* m = find_monitor_with_tag(client->tag);
   if (m) monitor_apply_layout(m);
   // ignore events from it
   XSelectInput(gDisplay, win, 0);
   XUngrabButton(gDisplay, AnyButton, AnyModifier, win);
   // permanently remove it
   for(int i=0; i<g_clients->len; i++){
      if(g_array_index(g_clients, Client*, i) == client)
         g_array_remove_index(g_clients, i);
   }
}
示例#15
0
文件: main.c 项目: xiaq/hlwm
void enternotify(XEvent* event) {
    XCrossingEvent *ce = &event->xcrossing;
    HSDebug("name is: EnterNotify, focus = %d\n", event->xcrossing.focus);
    if (!mouse_is_dragging()
        && *g_focus_follows_mouse
        && false == ce->focus) {
        HSClient* c = get_client_from_window(ce->window);
        HSFrame* target;
        if (c && c->tag->floating == false
              && (target = find_frame_with_window(c->tag->frame, ce->window))
              && target->content.clients.layout == LAYOUT_MAX
              && frame_focused_window(target) != ce->window) {
            // don't allow focus_follows_mouse if another window would be
            // hidden during that focus change (which only occurs in max layout)
        } else {
            focus_window(ce->window, false, true);
        }
    }
}
示例#16
0
文件: main.c 项目: xiaq/hlwm
void maprequest(XEvent* event) {
    HSDebug("name is: MapRequest\n");
    XMapRequestEvent* mapreq = &event->xmaprequest;
    if (is_herbstluft_window(g_display, mapreq->window)) {
        // just map the window if it wants that
        XWindowAttributes wa;
        if (!XGetWindowAttributes(g_display, mapreq->window, &wa)) {
            return;
        }
        XMapWindow(g_display, mapreq->window);
    } else if (!get_client_from_window(mapreq->window)) {
        // client should be managed (is not ignored)
        // but is not managed yet
        HSClient* client = manage_client(mapreq->window);
        if (client && find_monitor_with_tag(client->tag)) {
            XMapWindow(g_display, mapreq->window);
        }
    }
    // else: ignore all other maprequests from windows
    // that are managed already
}
示例#17
0
文件: main.c 项目: kcirick/fusionwm
void propertynotify(XEvent* event) {
    XPropertyEvent *ev = &event->xproperty;
    Client* client;

    if((client = wintosystrayicon(ev->window))) {
       if(ev->atom == XA_WM_NORMAL_HINTS)
          updatesystrayicongeom(client, client->last_size.width, client->last_size.height);

       resizebarwin(get_current_monitor());
       updatesystray();
    }

    if((ev->window == gRoot) && (ev->atom == XA_WM_NAME))  update_status();

    if (ev->state == PropertyNewValue &&
          (client = get_client_from_window(ev->window))) {
       if (ev->atom == XA_WM_HINTS)       client_update_wm_hints(client);
       else if (ev->atom == XA_WM_NAME)   client_update_title(client);
    }
    draw_bars();
}
示例#18
0
void propertynotify(XEvent* event) {
    // printf("name is: PropertyNotify\n");
    XPropertyEvent *ev = &event->xproperty;
    HSClient* client;
    if (ev->state == PropertyNewValue) {
        if (is_ipc_connectable(event->xproperty.window)) {
            ipc_handle_connection(event->xproperty.window);
        } else if((client = get_client_from_window(ev->window))) {
            if (ev->atom == XA_WM_HINTS) {
                client_update_wm_hints(client);
            } else if (ev->atom == XA_WM_NORMAL_HINTS) {
                updatesizehints(client);
                HSMonitor* m = find_monitor_with_tag(client->tag);
                if (m) monitor_apply_layout(m);
            } else if (ev->atom == XA_WM_NAME ||
                       ev->atom == g_netatom[NetWmName]) {
                client_update_title(client);
            }
        }
    }
}
示例#19
0
文件: main.c 项目: xiaq/hlwm
void propertynotify(XEvent* event) {
    // printf("name is: PropertyNotify\n");
    XPropertyEvent *ev = &event->xproperty;
    HSClient* client;
    if (ev->state == PropertyNewValue) {
        if (is_ipc_connectable(event->xproperty.window)) {
            ipc_handle_connection(event->xproperty.window);
        } else if((client = get_client_from_window(ev->window))) {
            switch (ev->atom) {
                case XA_WM_HINTS:
                    client_update_wm_hints(client);
                    break;
                case XA_WM_NAME:
                    client_update_title(client);
                    break;
                default:
                    break;
            }
        }
    }
}
示例#20
0
// scan for windows and add them to the list of managed clients
// from dwm.c
void scan(void) {
    unsigned int num;
    Window d1, d2, *cl, *wins = NULL;
    unsigned long cl_count;
    XWindowAttributes wa;

    ewmh_get_original_client_list(&cl, &cl_count);
    if (XQueryTree(g_display, g_root, &d1, &d2, &wins, &num)) {
        for (int i = 0; i < num; i++) {
            if(!XGetWindowAttributes(g_display, wins[i], &wa)
            || wa.override_redirect || XGetTransientForHint(g_display, wins[i], &d1))
                continue;
            // only manage mapped windows.. no strange wins like:
            //      luakit/dbus/(ncurses-)vim
            // but manage it if it was in the ewmh property _NET_CLIENT_LIST by
            // the previous window manager
            // TODO: what would dwm do?
            if (is_window_mapped(g_display, wins[i])
                || 0 <= array_find(cl, cl_count, sizeof(Window), wins+i)) {
                manage_client(wins[i]);
                XMapWindow(g_display, wins[i]);
            }
        }
        if(wins)
            XFree(wins);
    }
    // ensure every original client is managed again
    for (int i = 0; i < cl_count; i++) {
        if (get_client_from_window(cl[i])) continue;
        if (!XGetWindowAttributes(g_display, cl[i], &wa)
            || wa.override_redirect
            || XGetTransientForHint(g_display, cl[i], &d1))
        {
            continue;
        }
        XReparentWindow(g_display, cl[i], g_root, 0,0);
        manage_client(cl[i]);
    }
}
示例#21
0
文件: clientlist.c 项目: xiaq/hlwm
void unmanage_client(Window win) {
    HSClient* client = get_client_from_window(win);
    if (!client) {
        return;
    }
    if (client->dragged) {
        mouse_stop_drag();
    }
    // remove from tag
    frame_remove_window(client->tag->frame, win);
    // ignore events from it
    XSelectInput(g_display, win, 0);
    //XUngrabButton(g_display, AnyButton, AnyModifier, win);
    // permanently remove it
    HSTag* tag = client->tag;
    g_hash_table_remove(g_clients, &win);
    // and arrange monitor after the client has been removed from the stack
    HSMonitor* m = find_monitor_with_tag(tag);
    tag_update_focus_layer(tag);
    if (m) monitor_apply_layout(m);
    ewmh_remove_client(win);
    tag_set_flags_dirty();
}
示例#22
0
//------
void ewmh_handle_client_message(XEvent* event) {
   XWindowAttributes wa;
	XSetWindowAttributes swa;
   XClientMessageEvent* me = &(event->xclient);
   Client* client;

   if(systray_visible && 
         me->window == gSystray->window && 
         me->message_type == g_netatom[NetSystemTrayOP]) {
      // add systray icons
      if(me->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
         if(!(client = (Client *)calloc(1, sizeof(Client))))
            die("FATAL", "Could not malloc() %u bytes", sizeof(Client));

         client->window = me->data.l[2];
         client->next = gSystray->icon;
         gSystray->icon = client;
         XGetWindowAttributes(gDisplay, client->window, &wa);
         client->last_size.x = client->last_size.y = 0;
         client->last_size.width = wa.width;
         client->last_size.height = wa.height;
         client->float_size = client->last_size;
         client->floating = True;
         /* reuse tags field as mapped status */
         client->tag = g_array_index(g_tags, Tag*, 1);
         updatesystrayicongeom(client, wa.width, wa.height);
         XAddToSaveSet(gDisplay, client->window);
         XSelectInput(gDisplay, client->window, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
         XReparentWindow(gDisplay, client->window, gSystray->window, 0, 0);
         /* use parents background pixmap */
         swa.background_pixmap = ParentRelative;
         swa.background_pixel  = dc.colors[0][ColBG];
         XChangeWindowAttributes(gDisplay, client->window, CWBackPixmap|CWBackPixel, &swa);
         updatesystray();
         resizebarwin(get_current_monitor());
         //update_bars();
         //setclientstate(c, NormalState);
         long data[] = {NormalState, None};
         XChangeProperty(gDisplay, client->window, g_wmatom[WMState], g_wmatom[WMState], 32, PropModeReplace, (unsigned char*)data, 2);
      }
      return;
   }

   client = get_client_from_window(me->window);
   if (!client) return;

   if(me->message_type == g_netatom[NetWmState]){
      /* me->data.l[1] and [2] describe the properties to alter */
      for (int prop = 1; prop <= 2; prop++) {
         if (me->data.l[prop] == 0) continue;
         if (!(g_netatom[NetWmStateFullscreen] == me->data.l[prop])) continue;

         bool new_value[] = {
            [ _NET_WM_STATE_REMOVE ] = false,
            [ _NET_WM_STATE_ADD    ] = true,
            [ _NET_WM_STATE_TOGGLE ] = !client->fullscreen,
         };
         int action = me->data.l[0];

         client_set_fullscreen(client, new_value[action]);
      }
   }
}
示例#23
0
void ewmh_handle_client_message(XEvent* event) {
    HSDebug("Received event: ClientMessage\n");
    XClientMessageEvent* me = &(event->xclient);
    int index;
    for (index = 0; index < NetCOUNT; index++) {
        if (me->message_type == g_netatom[index]) {
            break;
        }
    }
    if (index >= NetCOUNT) {
        HSDebug("received unknown client message\n");
        return;
    }
    HSClient* client;

    int desktop_index;
    switch (index) {
        case NetActiveWindow:
            // only steal focus it allowed to the current source
            // (i.e.  me->data.l[0] in this case as specified by EWMH)
            if (focus_stealing_allowed(me->data.l[0])) {
                HSClient* client = get_client_from_window(me->window);
                if (client) {
                    focus_client(client, true, true);
                }
            }
            break;

        case NetCurrentDesktop: {
            desktop_index = me->data.l[0];
            if (desktop_index < 0 || desktop_index >= tag_get_count()) {
                HSDebug("_NET_CURRENT_DESKTOP: invalid index \"%d\"\n",
                        desktop_index);
                break;
            }
            HSTag* tag = get_tag_by_index(desktop_index);
            monitor_set_tag(get_current_monitor(), tag);
            break;
        }

        case NetWmDesktop: {
            desktop_index = me->data.l[0];
            if (!focus_stealing_allowed(me->data.l[1])) {
                break;
            }
            HSTag* target = get_tag_by_index(desktop_index);
            client = get_client_from_window(me->window);
            if (client && target) {
                tag_move_client(client, target);
            }
            break;
        }

        case NetWmState: {
            client = get_client_from_window(me->window);
            /* ignore requests for unmanaged windows */
            if (!client || !client->ewmhrequests) break;

            /* mapping between EWMH atoms and client struct members */
            struct {
                int     atom_index;
                bool    enabled;
                void    (*callback)(HSClient*, bool);
            } client_atoms[] = {
                { NetWmStateFullscreen,
                    client->fullscreen,     client_set_fullscreen },
                { NetWmStateDemandsAttention,
                    client->urgent,         client_set_urgent },
            };

            /* me->data.l[1] and [2] describe the properties to alter */
            for (int prop = 1; prop <= 2; prop++) {
                if (me->data.l[prop] == 0) {
                    /* skip if no property is specified */
                    continue;
                }
                /* check if we support the property data[prop] */
                int i;
                for (i = 0; i < LENGTH(client_atoms); i++) {
                    if (g_netatom[client_atoms[i].atom_index]
                        == me->data.l[prop]) {
                        break;
                    }
                }
                if (i >= LENGTH(client_atoms)) {
                    /* property will not be handled */
                    continue;
                }
                auto new_value = ArrayInitializer<bool,3>({
                    { _NET_WM_STATE_REMOVE  , false },
                    { _NET_WM_STATE_ADD     , true },
                    { _NET_WM_STATE_TOGGLE  , !client_atoms[i].enabled },
                }).a;
                int action = me->data.l[0];
                if (action >= new_value.size()) {
                    HSDebug("_NET_WM_STATE: invalid action %d\n", action);
                }
                /* change the value */
                client_atoms[i].callback(client, new_value[action]);
            }
            break;
        }

        case NetWmMoveresize: {
            client = get_client_from_window(me->window);
            if (!client) {
                break;
            }
            int direction = me->data.l[2];
            if (direction == _NET_WM_MOVERESIZE_MOVE
                || direction == _NET_WM_MOVERESIZE_MOVE_KEYBOARD) {
                mouse_initiate_move(client, 0, NULL);
            } else if (direction == _NET_WM_MOVERESIZE_CANCEL) {
                if (mouse_is_dragging()) mouse_stop_drag();
            } else {
                // anything else is a resize
                mouse_initiate_resize(client, 0, NULL);
            }
            break;
        }

        default:
            HSDebug("no handler for the client message \"%s\"\n",
                    g_netatom_names[index]);
            break;
    }
}
示例#24
0
文件: clientlist.c 项目: xiaq/hlwm
HSClient* manage_client(Window win) {
    if (is_herbstluft_window(g_display, win)) {
        // ignore our own window
        return NULL;
    }
    if (get_client_from_window(win)) {
        return NULL;
    }
    // init client
    HSClient* client = create_client();
    client->pid = window_pid(g_display, win);
    HSMonitor* m = get_current_monitor();
    // set to window properties
    client->window = win;
    client_update_title(client);

    unsigned int border, depth;
    Window root_win;
    int x, y;
    unsigned int w, h;
    XGetGeometry(g_display, win, &root_win, &x, &y, &w, &h, &border, &depth);
    // treat wanted coordinates as floating coords
    client->float_size.x = x;
    client->float_size.y = y;
    client->float_size.width = w;
    client->float_size.height = h;

    // apply rules
    HSClientChanges changes;
    client_changes_init(&changes, client);
    rules_apply(client, &changes);
    if (changes.tag_name) {
        client->tag = find_tag(changes.tag_name->str);
    }

    if (!changes.manage) {
        client_changes_free_members(&changes);
        client_destroy(client);
        // map it... just to be sure
        XMapWindow(g_display, win);
        return NULL;
    }

    // actually manage it
    g_hash_table_insert(g_clients, &(client->window), client);
    client->window_str = g_string_sized_new(10);
    g_string_printf(client->window_str, "0x%lx", win);
    hsobject_link(g_client_object, &client->object, client->window_str->str);
    // insert to layout
    if (!client->tag) {
        client->tag = m->tag;
    }
    // get events from window
    XSelectInput(g_display, win, CLIENT_EVENT_MASK);
    // insert window to the stack
    client->slice = slice_create_client(client);
    stack_insert_slice(client->tag->stack, client->slice);
    // insert window to the tag
    frame_insert_window(lookup_frame(client->tag->frame, changes.tree_index->str), win);
    client_update_wm_hints(client);
    if (changes.focus) {
        // give focus to window if wanted
        // TODO: make this faster!
        // WARNING: this solution needs O(C + exp(D)) time where W is the count
        // of clients on this tag and D is the depth of the binary layout tree
        frame_focus_window(client->tag->frame, win);
    }

    HSAttribute attributes[] = {
        ATTRIBUTE_STRING(   "winid",        client->window_str,     ATTR_READ_ONLY),
        ATTRIBUTE_STRING(   "title",        client->title,          ATTR_READ_ONLY),
        ATTRIBUTE_BOOL(     "fullscreen",   client->fullscreen,     client_attr_fullscreen),
        ATTRIBUTE_BOOL(     "pseudotile",   client->pseudotile,     client_attr_pseudotile),
        ATTRIBUTE_BOOL(     "ewmhrequests", client->ewmhrequests,   ATTR_ACCEPT_ALL),
        ATTRIBUTE_BOOL(     "ewmhnotify",   client->ewmhnotify,     ATTR_ACCEPT_ALL),
        ATTRIBUTE_BOOL(     "sizehints",    client->sizehints,      ATTR_ACCEPT_ALL),
        ATTRIBUTE_BOOL(     "urgent",       client->urgent,         client_attr_urgent),
        ATTRIBUTE_LAST,
    };
    hsobject_set_attributes(&client->object, attributes);

    ewmh_window_update_tag(client->window, client->tag);
    tag_set_flags_dirty();
    client_set_fullscreen(client, changes.fullscreen);
    ewmh_update_window_state(client);
    // add client after setting the correct tag for the new client
    // this ensures a panel can read the tag property correctly at this point
    ewmh_add_client(client->window);

    HSMonitor* monitor = find_monitor_with_tag(client->tag);
    if (monitor) {
        if (monitor != get_current_monitor()
            && changes.focus && changes.switchtag) {
            monitor_set_tag(get_current_monitor(), client->tag);
        }
        // TODO: monitor_apply_layout() maybe is called twice here if it
        // already is called by monitor_set_tag()
        monitor_apply_layout(monitor);
    } else {
        if (changes.focus && changes.switchtag) {
            monitor_set_tag(get_current_monitor(), client->tag);
        }
    }

    client_changes_free_members(&changes);
    grab_client_buttons(client, false);

    return client;
}
示例#25
0
文件: ewmh.c 项目: xiaq/hlwm
void ewmh_handle_client_message(XEvent* event) {
    HSDebug("Received event: ClientMessage\n");
    XClientMessageEvent* me = &(event->xclient);
    int index;
    for (index = 0; index < NetCOUNT; index++) {
        if (me->message_type == g_netatom[index]) {
            break;
        }
    }
    if (index >= NetCOUNT) {
        HSDebug("received unknown client message\n");
        return;
    }
    HSClient* client;

    int desktop_index;
    switch (index) {
        case NetActiveWindow:
            // only steal focus it allowed to the current source
            // (i.e.  me->data.l[0] in this case as specified by EWMH)
            if (focus_stealing_allowed(me->data.l[0])) {
                focus_window(me->window, true, true);
            }
            break;

        case NetCurrentDesktop:
            desktop_index = me->data.l[0];
            if (desktop_index < 0 || desktop_index >= g_tags->len) {
                HSDebug("_NET_CURRENT_DESKTOP: invalid index \"%d\"\n",
                        desktop_index);
                break;
            }
            HSTag* tag = g_array_index(g_tags, HSTag*, desktop_index);
            monitor_set_tag(get_current_monitor(), tag);
            break;

        case NetWmDesktop:
            desktop_index = me->data.l[0];
            if (!focus_stealing_allowed(me->data.l[1])) {
                break;
            }
            HSTag* target = get_tag_by_index(desktop_index);
            client = get_client_from_window(me->window);
            if (client && target) {
                tag_move_client(client, target);
            }
            break;

        case NetWmState:
            client = get_client_from_window(me->window);
            /* ignore requests for unmanaged windows */
            if (!client || !client->ewmhrequests) break;

            /* mapping between EWMH atoms and client struct members */
            struct {
                int     atom_index;
                bool    enabled;
                void    (*callback)(HSClient*, bool);
            } client_atoms[] = {
                { NetWmStateFullscreen,
                    client->fullscreen,     client_set_fullscreen },
                { NetWmStateDemandsAttention,
                    client->urgent,         client_set_urgent },
            };

            /* me->data.l[1] and [2] describe the properties to alter */
            for (int prop = 1; prop <= 2; prop++) {
                if (me->data.l[prop] == 0) {
                    /* skip if no property is specified */
                    continue;
                }
                /* check if we support the property data[prop] */
                int i;
                for (i = 0; i < LENGTH(client_atoms); i++) {
                    if (g_netatom[client_atoms[i].atom_index]
                        == me->data.l[prop]) {
                        break;
                    }
                }
                if (i >= LENGTH(client_atoms)) {
                    /* property will not be handled */
                    continue;
                }
                bool new_value[] = {
                    [ _NET_WM_STATE_REMOVE  ] = false,
                    [ _NET_WM_STATE_ADD     ] = true,
                    [ _NET_WM_STATE_TOGGLE  ] = !client_atoms[i].enabled,
                };
                int action = me->data.l[0];
                if (action >= LENGTH(new_value)) {
                    HSDebug("_NET_WM_STATE: invalid action %d\n", action);
                }
                /* change the value */
                client_atoms[i].callback(client, new_value[action]);
            }
            break;

        default:
            HSDebug("no handler for the client message \"%s\"\n",
                    g_netatom_names[index]);
            break;
    }
}
示例#26
0
文件: clientlist.c 项目: xiaq/hlwm
HSClient* get_current_client() {
    Window win = frame_focused_window(g_cur_frame);
    if (!win) return NULL;
    return get_client_from_window(win);
}