////////////////////////////////////////////// // NovaWM - Nova Window Manager for X11 // ////////////////////////////////////////////// // By: Tim Walters // ////////////////////////////////////////////// // Copyright (C) 2001-2002 Tim Walters // ////////////////////////////////////////////// //////////////////////////////////////////////////////////////// //This code is released under the terms of the GNU GPL. Refer // //to the license file included with this source code. // //////////////////////////////////////////////////////////////// #include "novawm.h" void Events::NovaWM_EventLoop () { XEvent event; fd_set fd; struct timeval tv; time_t now; struct tm *lt; int i; int xfd = ConnectionNumber (display); while (1) { now = time (0); lt = gmtime (&now); tv.tv_usec = 0; tv.tv_sec = 60 - lt->tm_sec; FD_ZERO (&fd); FD_SET (xfd, &fd); if (select (xfd + 1, &fd, 0, 0, &tv) == 0) novawm.UpdateClock (); while (XPending (display)) { XNextEvent (display, &event); switch (event.type) { case Expose: Event_Expose (&event.xexpose); break; case ButtonPress: Event_ButtonDown (&event.xbutton); break; case ButtonRelease: Event_ButtonUp (&event.xbutton); break; case MotionNotify: Event_Motion (&event.xcrossing); break; case MapRequest: Event_Map (&event.xmaprequest); break; case UnmapNotify: Event_Unmap (&event.xunmap); break; case DestroyNotify: Event_Destroy (&event.xdestroywindow); break; case ConfigureRequest: Event_Configure (&event.xconfigurerequest); break; case PropertyNotify: Event_Property (&event.xproperty); break; case ColormapNotify: Event_Colormap (&event.xcolormap); break; case ClientMessage: Event_ClientMessage (&event.xclient); break; case FocusIn: Event_FocusIn (&event.xfocus); break; case FocusOut: Event_FocusOut (&event.xfocus); break; case EnterNotify: Event_EnterWindow (&event.xcrossing); break; case LeaveNotify: Event_LeaveWindow (&event.xcrossing); break; case KeyRelease: Event_KeyUp (&event.xkey); } } } } void Events::Event_Expose (XExposeEvent * event) { #ifdef DEBUG //printf ("DEBUG Expose()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (event->window == rootMenu.menuWindow ()) { rootMenu.DrawItems (); } if (event->window == listMenu.menuWindow ()) { listMenu.DrawItems (); } if (event->window == windowMenu.menuWindow ()) { windowMenu.DrawItems (); } if ((event->window == novawm.NovaBar) || (event->window == novawm.nbClock) || (event->window == novawm.nbCurWin) || (event->window == novawm.nbListButton) || (event->window == novawm.nbButton)) { //This was added for Nautilus problems but removed //because the bar would show up in full screen apps(like games) //XRaiseWindow (display, novawm.NovaBar); novawm.DrawBar (); } if (event->window == novawm.nbWinList) novawm.DrawWinList (); if (!window) return; winmgr.Redraw (window); } void Events::Event_ButtonDown (XButtonEvent * event) { #ifdef DEBUG printf ("DEBUG ButtonDown()\n"); #endif if ((event->window == novawm.nbListButton) || (event->window == novawm.nbButton) || (event->window == novawm.nbWLstScrllUp) || (event->window == novawm.nbWLstScrllDwn)) { DrawDown (event->window); return; } Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; // window->ignoreTransient = true; // winmgr.SetFocus (window); // window->ignoreTransient = false; if (cfg.disableBar == true) { if (listMenu.isOpen () == true) listMenu.Destroy (); if (windowMenu.isOpen () == true) windowMenu.Destroy (); if (rootMenu.isOpen () == true) rootMenu.Destroy (); } //Check the titlebar buttons if (event->button == Button1) { if ((event->window == window->kill) || (event->window == window->stretch) || (event->window == window->hide)) { DrawDown (event->window); return; } } XAllowEvents (display, ReplayPointer, CurrentTime); if (window != winmgr.focusWindow) //Raise and give focus to the window { window->ignoreTransient = true; winmgr.SetFocus (window); window->ignoreTransient = false; return; } if (event->y > 18) //Make sure it IS on the titlebar return; if (event->button == Button1 && window->titlebar == event->window) { window->ignoreTransient = true; winmgr.SetFocus (window); window->ignoreTransient = false; winmgr.Move (window); } } void Events::Event_ButtonUp (XButtonEvent * event) { #ifdef DEBUG printf ("DEBUG ButtonUp()\n"); #endif if (downWindow) { if (event->window == novawm.nbButton) { downWindow = None; novawm.DrawBar (); } else { DrawUp (downWindow); downWindow = None; } } //Always close the menus after another click if (novaMenu.isOpen () == true) { if (event->window == novaMenu.menuWindow ()) novawm.novaMenu_Click (novaMenu.GetSelection ()); novaMenu.Destroy (); } if (rootMenu.isOpen () == true) { if (event->window == rootMenu.menuWindow ()) rootMenu_Click (rootMenu.GetSelection ()); rootMenu.Destroy (); } if (listMenu.isOpen () == true) { if (event->window == listMenu.menuWindow ()) winmgr.listMenu_Click (listMenu.GetSelection ()); listMenu.Destroy (); } if (windowMenu.isOpen () == true) { if (event->window == windowMenu.menuWindow ()) windowMenu_Click (windowMenu.GetSelection ()); windowMenu.Destroy (); } if (cfg.disableBar == true) { if (event->window == root && event->button == Button2) { if (listMenu.isOpen () != true) winmgr.Create_ListMenu (event->x_root, event->y_root); else { winmgr.nListWindow = 0; // if(winmgr.listWindow) // delete winmgr.listWindow; listMenu.Destroy (); } } if (event->window == root && event->button == Button3) { if (rootMenu.isOpen () != true) rootMenu.Create (event->x_root, event->y_root); else rootMenu.Destroy (); } } if (event->window == novawm.nbButton) if (novaMenu.isOpen () != true) novaMenu.Create (novawm.bar_x, NOVABAR_HEIGHT + 1); else novaMenu.Destroy (); if (event->window == novawm.nbWLstScrllUp) novawm.List_Scroll (-1); if (event->window == novawm.nbWLstScrllDwn) novawm.List_Scroll (1); //Get selection and close window list if ((novawm.lstItems >= 0) && (event->window != novawm.nbWLstScrllDwn) && (event->window != novawm.nbWLstScrllUp) && (event->window != novawm.nbWLstScrllBar)) { //A item is selected, give it focus if ((novawm.selItem + novawm.topItem >= 0) && (novawm.selItem + novawm.topItem <= novawm.lstItems) && (event->window == novawm.nbWLstItemWin)) { //The selection handling here is the same with the menu. winmgr.listMenu_Click (novawm.selItem + novawm.topItem); } //Close the window list novawm.DestroyWinList (); } if (event->window == novawm.nbListButton) { novawm.CreateWinList (); return; } Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; //Check the titlebar buttons if (event->window == window->kill) winmgr.Kill (window); if (event->window == window->stretch) winmgr.Stretch (window); if (event->window == window->hide) winmgr.Hide (window); if (event->window == window->titlebar && event->button == Button2) window->Shade (); if (event->window == window->titlebar && event->button == Button3) { if (windowMenu.isOpen () != true) windowMenu.Create (event->x_root, event->y_root); else windowMenu.Destroy (); } } void Events::Event_Map (XMapRequestEvent * event) { #ifdef DEBUG printf ("DEBUG: Map()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) { winmgr.NewWindow (event->window); return; } winmgr.NewWindow (event->window); if (window->hasTitlebar == true) XMapWindow (display, window->titlebar); XMapWindow (display, window->window); window->SetState (NormalState); } void Events::Event_Unmap (XUnmapEvent * event) { #ifdef DEBUG printf ("DEBUG Unmap()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (winmgr.Find_UnmapIgnore (event->window) == 1) { #ifdef DEBUG printf ("novawm: DEBUG: ignoring unmap\n"); #endif winmgr.RemoveUnmapIgnore (event->window); //unmapignore--; return; } XUnmapWindow(display,event->window); if (!window) { #ifdef DEBUG printf ("DEBUG: Ignoring unmanaged window.\n"); #endif // XUnmapWindow (display, event->window); return; } #ifdef DEBUG printf ("DEBUG: Unmap() -- Destroying window.\n"); #endif window->Destroy (); } void Events::Event_Motion (XCrossingEvent * event) { //#ifdef DEBUG // printf("DEBUG Motion()\n"); //#endif if (event->window == novawm.nbWLstItemWin) novawm.HighlightListItem (event->y); if (event->window == rootMenu.menuWindow ()) rootMenu.HighlightItem (event->x, event->y); if (event->window == windowMenu.menuWindow ()) windowMenu.HighlightItem (event->x, event->y); if (event->window == novaMenu.menuWindow ()) novaMenu.HighlightItem (event->x, event->y); if (event->window == listMenu.menuWindow ()) listMenu.HighlightItem (event->x, event->y); } void Events::Event_Destroy (XDestroyWindowEvent * event) { #ifdef DEBUG printf ("DEBUG Destroy()\n"); #endif Novawm_Window *win = winmgr.WindowSearch (event->window); if (!win) //Ignore destroy events of unmanaged windows { // XDestroyWindow (display, event->window); return; } win->Destroy (); } void Events::Event_Configure (XConfigureRequestEvent * event) { #ifdef DEBUG printf ("DEBUG Configure()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); XWindowChanges winchange; winchange.x = event->x; winchange.y = event->y; winchange.width = event->width; winchange.height = event->height; winchange.sibling = event->above; winchange.stack_mode = event->detail; if (!window) //Not Managed { XConfigureWindow (display, event->window, event->value_mask, &winchange); XRaiseWindow (display, event->window); // winmgr.NewWindow (event->window); } else //Managed { window->x = event->x; window->y = event->y; window->orig_x = event->x; window->orig_y = event->y; window->width = event->width; window->height = event->height; window->orig_width = event->width; window->orig_height = event->height; if (window->hasTitlebar != true) //Doesn't have a titlebar { XMoveWindow (display, window->window, event->x, event->y); } else //Has a titlebar { XMoveWindow (display, window->titlebar, event->x, event->y); XResizeWindow (display, window->titlebar, event->width, event->height + 20); } XResizeWindow (display, window->window, event->width, event->height); //Move the titlebar buttons XMoveWindow (display, window->kill, window->width - 19, 3); XMoveWindow (display, window->stretch, window->width - 37, 3); XMoveWindow (display, window->hide, window->width - 54, 3); //XRaiseWindow (display, window->titlebar); //XRaiseWindow (display, window->window); window->ignoreTransient = true; winmgr.SetFocus (window); window->ignoreTransient = false; } } void Events::Event_Property (XPropertyEvent * event) { char *title; #ifdef DEBUG printf ("DEBUG Property()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if (event->atom == XA_WM_NAME) { XFetchName (display, window->window, &title); if (!title) window->title = "Unknown"; else window->title = title; XClearWindow (display, window->titlebar); winmgr.Redraw (window); novawm.DrawBar (); } } void Events::Event_Colormap (XColormapEvent * event) { #ifdef DEBUG printf ("DEBUG ColormapNotify()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if (event->c_new) //New Colormap { window->colorMap = event->c_new; XInstallColormap (display, event->c_new); } } void Events::Event_ClientMessage (XClientMessageEvent * event) { #ifdef DEBUG printf ("DEBUG ClientMessage()\n"); #endif #ifdef _WIN_GNOME_SUPPORT if ((event->message_type == winProtocols_Workspace) && (event->window == root)) { winmgr.SetDesktop (event->data.l[0]); return; } #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if (event->message_type == netStateAtom) { if ((event->data.l[1] == netStateStickyAtom) || (event->data.l[2] == netStateStickyAtom)) { if (event->data.l[0] == _NET_WM_STATE_ADD) window->isSticky = true; if (event->data.l[0] == _NET_WM_STATE_REMOVE) window->isSticky = false; if (event->data.l[0] == _NET_WM_STATE_TOGGLE) window->isSticky = (window->isSticky) ? true : false; } } if (event->message_type == netDesktopAtom) { winmgr.SendToDesktop (window, event->data.l[0]); return; } #ifdef _WIN_GNOME_SUPPORT if (event->message_type == winProtocols_Workspace) { winmgr.SendToDesktop (window, event->data.l[0]); return; } #endif if (event->data.l[0] == IconicState) { winmgr.Hide (window); } if (event->data.l[0] == NormalState) { winmgr.SetFocus (window); } } void Events::Event_FocusIn (XFocusChangeEvent * event) { #ifdef DEBUG printf ("DEBUG: FocusIn()\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; //protocolAtom,SubstructureRedirectMask,takefocusAtom XEvent sendEvent; sendEvent.type = ClientMessage; sendEvent.xclient.window = window->window; sendEvent.xclient.message_type = protocolAtom; sendEvent.xclient.format = 32; sendEvent.xclient.data.l[0] = takefocusAtom; XSendEvent (display, window->window, false, SubstructureRedirectMask, &sendEvent); //Grab the previous desktop key XGrabKey (display, XKeysymToKeycode (display, XK_bracketleft), ControlMask, event->window, true, GrabModeAsync, GrabModeAsync); //Grab the next desktop key XGrabKey (display, XKeysymToKeycode (display, XK_bracketright), ControlMask, event->window, true, GrabModeAsync, GrabModeAsync); //Set the colormap (Only added colormap support for a few programs) XInstallColormap (display, window->colorMap); /* XGrabButton(display,Button1,AnyModifier, window->window, 1,ButtonPressMask, GrabModeSync,GrabModeAsync, None,None); */ } void Events::Event_FocusOut (XFocusChangeEvent * event) { #ifdef DEBUG printf ("DEBUG FocusOut\n"); #endif Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if (event->mode == NotifyNormal) { winmgr.focusWindow = 0; } //Grab the previous desktop key XUngrabKey (display, XKeysymToKeycode (display, XK_bracketleft), ControlMask, event->window); //Grab the next desktop key XUngrabKey (display, XKeysymToKeycode (display, XK_bracketright), ControlMask, event->window); XSetInputFocus (display, root, RevertToNone, CurrentTime); // XUngrabButton(display,Button1,AnyModifier, // window->window); } void Events::Event_EnterWindow (XCrossingEvent * event) { Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if (focusType == 0) XSetInputFocus (display, window->window, RevertToNone, CurrentTime); if (event->window == window->hide) XSetInputFocus (display, window->hide, RevertToNone, CurrentTime); if (event->window == window->stretch) XSetInputFocus (display, window->stretch, RevertToNone, CurrentTime); if (event->window == window->kill) XSetInputFocus (display, window->kill, RevertToNone, CurrentTime); } void Events::Event_LeaveWindow (XCrossingEvent * event) { Novawm_Window *window = winmgr.WindowSearch (event->window); if (!window) return; if ((event->window == window->kill) || (event->window == window->stretch) || (event->window == window->hide)) XSetInputFocus (display, window->window, RevertToNone, CurrentTime); } void Events::Event_KeyUp (XKeyEvent * event) { #ifdef DEBUG printf ("DEBUG: KeyUp()\n"); #endif KeySym keysym = XKeycodeToKeysym (display, event->keycode, 0); switch (keysym) { case XK_bracketleft: winmgr.SetDesktop (winmgr.cDesktop - 1); break; case XK_bracketright: winmgr.SetDesktop (winmgr.cDesktop + 1); break; } } void Events::rootMenu_Click (int item) { if (item == 0) //xterm novawm.Run ("xterm"); if (item == 5) //Restart novawm.Restart (); if (item == 6) //Shutdown novawm.Shutdown (); } void Events::windowMenu_Click (int item) { if (item == 0) { winmgr.Hide (winmgr.focusWindow); } if (item == 1) winmgr.Stretch (winmgr.focusWindow); if (item == 2) winmgr.Resize (winmgr.focusWindow); if (item == 3) winmgr.Kill (winmgr.focusWindow); //Item 4 is the divider/splitter line if (item == 5) winmgr.SendToDesktop (winmgr.focusWindow, 0); if (item == 6) winmgr.SendToDesktop (winmgr.focusWindow, 1); if (item == 7) winmgr.SendToDesktop (winmgr.focusWindow, 2); if (item == 8) winmgr.SendToDesktop (winmgr.focusWindow, 3); if (item == 9) winmgr.SendToDesktop (winmgr.focusWindow, winmgr.cDesktop + 1); if (item == 10) winmgr.SendToDesktop (winmgr.focusWindow, winmgr.cDesktop - 1); } //The following DrawDown() and DrawUp() functions were mainly //created button borders //This is to simplify drawing a lowered/down border of a window void Events::DrawDown (Window window) { #ifdef DEBUG //printf ("DEBUG: DrawDown()\n"); #endif XWindowAttributes win_attrib; XGetWindowAttributes (display, window, &win_attrib); downWindow = window; XSetForeground (display, novawm_gc, BlackPixel (display, screen)); XDrawLine (display, window, novawm_gc, 0, 0, win_attrib.width, 0); XDrawLine (display, window, novawm_gc, 0, 0, 0, win_attrib.height); XSetForeground (display, novawm_gc, WhitePixel (display, screen)); XDrawLine (display, window, novawm_gc, 0, win_attrib.height - 1, win_attrib.width, win_attrib.height - 1); XDrawLine (display, window, novawm_gc, win_attrib.width - 1, 1, win_attrib.width - 1, win_attrib.height); } //This is to simplify drawing a raised/up border of a window void Events::DrawUp (Window window) { #ifdef DEBUG //printf ("DEBUG: DrawUp()\n"); #endif XWindowAttributes win_attrib; XGetWindowAttributes (display, window, &win_attrib); downWindow = window; XSetForeground (display, novawm_gc, BlackPixel (display, screen)); XDrawLine (display, window, novawm_gc, 0, win_attrib.height - 1, win_attrib.width, win_attrib.height - 1); XDrawLine (display, window, novawm_gc, win_attrib.width - 1, 1, win_attrib.width - 1, win_attrib.height); XSetForeground (display, novawm_gc, WhitePixel (display, screen)); XDrawLine (display, window, novawm_gc, 0, 0, win_attrib.width, 0); XDrawLine (display, window, novawm_gc, 0, 0, 0, win_attrib.height); }