⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wm_state.c

📁 基于linux的DVD播放器程序
💻 C
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include <X11/Xatom.h>#include <inttypes.h>#include <string.h>#include "debug_print.h"#include "display.h"#include "wm_state.h"static WindowState_t current_state = WINDOW_STATE_NORMAL;typedef struct {  int x;  int y;  int width;  int height;} geometry_t;static geometry_t normal_state_geometry;static unsigned long req_serial;        /* used for error handling */static int (*prev_xerrhandler)(Display *dpy, XErrorEvent *ev);static void remove_motif_decorations(Display *dpy, Window win);static void disable_motif_decorations(Display *dpy, Window win);static int EWMH_wm;static int gnome_wm;static int gnome_wm_layers;static int has_ewmh_state_fullscreen;static char *wm_name = NULL;static Atom wm_state_atom;#define MWM_HINTS_DECORATIONS   (1L << 1)typedef struct {  uint32_t flags;  uint32_t functions;  uint32_t decorations;  int32_t  input_mode;  uint32_t status;} mwmhints_t;static void remove_motif_decorations(Display *dpy, Window win){  Atom WM_HINTS;    /* can only change decorations while unmapped ? */    /* First try to set MWM hints */  WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);  if(WM_HINTS != None) {    /* Hints used by Motif compliant window managers */    mwmhints_t MWMHints = { MWM_HINTS_DECORATIONS, 0, 0, 0, 0 };        XChangeProperty(dpy, win,		    WM_HINTS, WM_HINTS, 32,		    PropModeReplace,		    (unsigned char *)&MWMHints,		    sizeof(MWMHints)/sizeof(long));  } else {    WARNING("%s", "_MOTIF_WM_HINTS atom not found\n");  }}static void disable_motif_decorations(Display *dpy, Window win){  Atom WM_HINTS;    /* can only change decorations while unmapped ? */    /* First try to unset MWM hints */  WM_HINTS = XInternAtom(dpy, "_MOTIF_WM_HINTS", True);  if(WM_HINTS != None) {    /* Hints used by Motif compliant window managers */    XDeleteProperty(dpy, win, WM_HINTS);  } else {    WARNING("%s", "_MOTIF_WM_HINTS atom not found\n");  }  }static void calc_coords(Display *dpy, Window win, int *x, int *y, XEvent *ev){  int dest_x_ret;  int dest_y_ret;  Window dest_win;    DNOTE("configure x: %d, y: %d\n",	ev->xconfigure.x,  ev->xconfigure.y);  if(ev->xconfigure.send_event == True) {    //DNOTE("send_event: True\n");    *x = ev->xconfigure.x;    *y = ev->xconfigure.y;        XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), 			  0,			  0,			  &dest_x_ret,			  &dest_y_ret,			  &dest_win);        if(*x != dest_x_ret) {      DNOTE("wm_x: %d, xtranslate_x: %d\n", *x, dest_x_ret);      *x = dest_x_ret;    }    if(*y != dest_y_ret) {      DNOTE("wm_y: %d, xtranslate_y: %d\n", *y, dest_y_ret);      *y = dest_y_ret;    }      } else {        //DNOTE("send_event: False\n");        XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), 			  0,			  0,			  &dest_x_ret,			  &dest_y_ret,			  &dest_win);    DNOTE("xtranslate x: %d, y: %d\n", dest_x_ret, dest_y_ret);    *x = dest_x_ret;    *y = dest_y_ret;      }  //DNOTE("x: %d, y: %d\n", *x, *y);}static void save_normal_geometry(Display *dpy, Window win){  // Ugly hack so we can reposition ourself when going from fullscreen    Window root_return;  int x,y;  unsigned int bwidth, depth;  int dest_x_ret, dest_y_ret;  Window dest_win;    XGetGeometry(dpy, win, &root_return, &x, &y,	       &normal_state_geometry.width,	       &normal_state_geometry.height,	       &bwidth, &depth);    XTranslateCoordinates(dpy, win, DefaultRootWindow(dpy), 			0,			0,			&dest_x_ret,			&dest_y_ret,			&dest_win);    normal_state_geometry.x = dest_x_ret;  normal_state_geometry.y = dest_y_ret;    DNOTE("x_ret: %d, y_ret: %d\n", dest_x_ret, dest_y_ret);  DNOTE("normal_state_geometry: x: %d, y: %d, w: %d, h: %d, bw: %d, d: %d\n",	x, y,	normal_state_geometry.width,	normal_state_geometry.height,	bwidth, depth);  }static void restore_normal_geometry(Display *dpy, Window win){  XWindowChanges win_changes;  XEvent ev, ret_ev;  int x, y;  int n;  // Try to resize  win_changes.x = normal_state_geometry.x;  win_changes.y = normal_state_geometry.y;  win_changes.width = normal_state_geometry.width;  win_changes.height = normal_state_geometry.height;  //win_changes.stack_mode = Above;  XReconfigureWMWindow(dpy, win, 0,		       CWX | CWY |		       CWWidth | CWHeight,		       &win_changes);    // Wait for a configure notify  do {    XNextEvent(dpy, &ev);  } while(ev.type != ConfigureNotify);    // save the configure event so we can return it  ret_ev = ev;    calc_coords(dpy, win, &x, &y, &ev);  for(n = 0; n < 10; n++) {    while(XCheckTypedEvent(dpy, ConfigureNotify, &ev) == True) {      ret_ev = ev;      calc_coords(dpy, win, &x, &y, &ev);    }    if(abs(x-win_changes.x) < 100 &&       abs(y-win_changes.y) < 100) {      break;    }    usleep(100000);  }      //DNOTE("no more configure notify\n");  //try to move one more time, maybe we didn't get all configure events?  if(x != win_changes.x || y != win_changes.y) {    DNOTE("window is not at %d, %d. Trying to move again\n",	  win_changes.x, win_changes.y);        XSync(dpy, True);    XReconfigureWMWindow(dpy, win, 0, CWX | CWY,			 &win_changes);    /*        do {      XNextEvent(dpy, &ev);    } while(ev.type != ConfigureNotify);        ret_ev = ev;        calc_coords(dpy, win, &x, &y, &ev);    */    while(XCheckTypedEvent(dpy, ConfigureNotify, &ev) == True) {      ret_ev = ev;      calc_coords(dpy, win, &x, &y, &ev);    }  }   // ugly hack, but what can you do  //  when we don't end up at (win_changes.x, win_changes.y)  //  try to compensate and move one more time  if((x != win_changes.x || y != win_changes.y) &&     abs(x - win_changes.x) < 100 && abs(y - win_changes.y) < 100) {    XWindowChanges win_compensate;    win_compensate.x = win_changes.x+win_changes.x-x;    win_compensate.y = win_changes.y+win_changes.y-y;    DNOTE("window is not at %d, %d\n", win_changes.x, win_changes.y);    DNOTE("Compensating by moving to x: %d= %d+%d-%d, y: %d= %d+%d-%d\n",	  win_compensate.x, win_changes.x, win_changes.x, x,	  win_compensate.y, win_changes.y, win_changes.y, y);        XSync(dpy, True);    XReconfigureWMWindow(dpy, win, 0, CWX | CWY,			 &win_compensate);        do {      XNextEvent(dpy, &ev);    } while(ev.type != ConfigureNotify);        ret_ev = ev;    calc_coords(dpy, win, &x, &y, &ev);        while(XCheckTypedEvent(dpy, ConfigureNotify, &ev) == True) {      ret_ev = ev;      calc_coords(dpy, win, &x, &y, &ev);    }        if(x != win_changes.x || y != win_changes.y) {      DNOTE("Couldn't place window at %d,%d\n",	    win_changes.x, win_changes.y);      DNOTE("Window is at %d, %d\n",	    x, y);    } else {      //DNOTE("Fixed, window is now at %d,%d\n", win_changes.x, win_changes.y);    }      }    XPutBackEvent(dpy, &ev);  }int get_wm_state(Display *dpy, Window win){  Atom actual_type_return;  int actual_format_return;  unsigned long nitems_return;  unsigned long bytes_after_return;  unsigned char* prop_return;  int wm_state;    XGetWindowProperty(dpy, win, wm_state_atom, 0, 1,		     False, wm_state_atom,		     &actual_type_return,		     &actual_format_return,		     &nitems_return,		     &bytes_after_return,		     &prop_return);  if(actual_type_return == None) {    return -1; //the property does not exist  } else if(actual_type_return != wm_state_atom) {    WARNING("WM_STATE is not of type WM_STATE: %lu\n", 	    (unsigned long)actual_type_return);    return -1; //wrong property type  } else {    wm_state = (int)(((unsigned long *)prop_return)[0]);    XFree(prop_return);    return wm_state;  }}  static Bool withdraw_predicate(Display *dpy, XEvent *ev, XPointer arg){  if(ev->type == UnmapNotify ||     ev->type == ReparentNotify ||     ev->type == PropertyNotify) {    return True;  } else {    return False;  }}void withdraw_window(Display *dpy, Window win){  XEvent ev;  int n;  int wm_state;  int wait_for_wm_state = 1;  int wait_for_reparent = 1;  int wait_for_unmap = 1;  Window root_return, parent_return;  Window *children_return = NULL;  unsigned int nchildren_return;  wm_state = get_wm_state(dpy, win);  if(wm_state <= 0) {    // window is already withdrawn or no wm (supporting wm_state) is running    wait_for_wm_state = 0;  }  if(XQueryTree(dpy, win, &root_return, &parent_return,		&children_return, &nchildren_return)) {    if(root_return == parent_return) {      //no wm running or the wm is not reparenting      // if the wm is not reparenting it should support wm_state      wait_for_reparent = 0;    }    if(children_return) {      XFree(children_return);    }  } else {    WARNING("%s", "XQueryTree failed\n");    root_return = DefaultRootWindow(dpy);  }    XWithdrawWindow(dpy, win, DefaultScreen(dpy));    // Wait for window to be unmapped/withdrawn  // If a wm is running wait for WM_STATE==withdrawn  // or a reparent event (only works for a reparenting wm)  // to know when the wm is done with our window    // Always wait until we get an unmap notification.  // Also wait ~0.5s for reparent/wmstate==withdraw else continue  // and assume the wm is broken  for(n = 0;      wait_for_unmap || (n < 50 && (wait_for_reparent || wait_for_wm_state));      n++) {        while(XCheckIfEvent(dpy, &ev, withdraw_predicate, NULL) == True) {      switch(ev.type) {      case UnmapNotify:	wait_for_unmap = 0;	break;      case ReparentNotify:	if(ev.xreparent.parent == root_return) {	  wait_for_reparent = 0;	  //we don't have to wait for wmstate also	  //wait_for_wm_state = 0;	}	break;      case PropertyNotify:	if(ev.xproperty.atom == wm_state_atom) {	  wm_state = get_wm_state(dpy, win);	  if(wm_state <= 0) {	    //window has been withdrawn	    wait_for_wm_state = 0;	    //don't wait for reparent now	    wait_for_reparent = 0;	  }	}      default:	break;      }    }    usleep(10000);  }  if(n == 50) {    DNOTE("%s", "Withdraw window timeout, broken WM ?\n");  }}static void switch_to_fullscreen_state(Display *dpy, Window win){  XEvent ev;  XEvent ret_ev;  XWindowAttributes attrs;  XWindowChanges win_changes;  int x, y;  int n;  XSizeHints *sizehints;  // We don't want to have to replace the window manually when remapping it  sizehints = XAllocSizeHints();  sizehints->flags = USPosition | PWinGravity;  sizehints->x = 0; // obsolete but should be set in case  sizehints->y = 0; // there is an old wm used  sizehints->win_gravity = NorthWestGravity;  save_normal_geometry(dpy, win);    if(!has_ewmh_state_fullscreen) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -